06 Jan, 2012

1 commit

  • Reading /proc/pid/stat of another process checks if one has ptrace permissions
    on that process. If one does have permissions it outputs some data about the
    process which might have security and attack implications. If the current
    task does not have ptrace permissions the read still works, but those fields
    are filled with inocuous (0) values. Since this check and a subsequent denial
    is not a violation of the security policy we should not audit such denials.

    This can be quite useful to removing ptrace broadly across a system without
    flooding the logs when ps is run or something which harmlessly walks proc.

    Signed-off-by: Eric Paris
    Acked-by: Serge E. Hallyn

    Eric Paris
     

18 Jul, 2011

3 commits

  • The fake SIGSTOP during attach has numerous problems. PTRACE_SEIZE
    is already fine, but we have basically the same problems is SIGSTOP
    is sent on auto-attach, the tracer can't know if this signal signal
    should be cancelled or not.

    Change ptrace_event() to set JOBCTL_TRAP_STOP if the new child is
    PT_SEIZED, this triggers the PTRACE_EVENT_STOP report.

    Thereafter a PT_SEIZED task can never report the bogus SIGSTOP.

    Test-case:

    #define PTRACE_SEIZE 0x4206
    #define PTRACE_SEIZE_DEVEL 0x80000000
    #define PTRACE_EVENT_STOP 7
    #define WEVENT(s) ((s & 0xFF0000) >> 16)

    int main(void)
    {
    int child, grand_child, status;
    long message;

    child = fork();
    if (!child) {
    kill(getpid(), SIGSTOP);
    fork();
    assert(0);
    return 0x23;
    }

    assert(ptrace(PTRACE_SEIZE, child, 0,PTRACE_SEIZE_DEVEL) == 0);
    assert(wait(&status) == child);
    assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);

    assert(ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACEFORK) == 0);

    assert(ptrace(PTRACE_CONT, child, 0,0) == 0);
    assert(waitpid(child, &status, 0) == child);
    assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP);
    assert(WEVENT(status) == PTRACE_EVENT_FORK);

    assert(ptrace(PTRACE_GETEVENTMSG, child, 0, &message) == 0);
    grand_child = message;

    assert(waitpid(grand_child, &status, 0) == grand_child);
    assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP);
    assert(WEVENT(status) == PTRACE_EVENT_STOP);

    kill(child, SIGKILL);
    kill(grand_child, SIGKILL);
    return 0;
    }

    Signed-off-by: Oleg Nesterov
    Acked-by: Tejun Heo

    Oleg Nesterov
     
  • If the new child is traced, do_fork() adds the pending SIGSTOP.
    It assumes that either it is traced because of auto-attach or the
    tracer attached later, in both cases sigaddset/set_thread_flag is
    correct even if SIGSTOP is already pending.

    Now that we have PTRACE_SEIZE this is no longer right in the latter
    case. If the tracer does PTRACE_SEIZE after copy_process() makes the
    child visible the queued SIGSTOP is wrong.

    We could check PT_SEIZED bit and change ptrace_attach() to set both
    PT_PTRACED and PT_SEIZED bits simultaneously but see the next patch,
    we need to know whether this child was auto-attached or not anyway.

    So this patch simply moves this code to ptrace_init_task(), this
    way we can never race with ptrace_attach().

    Signed-off-by: Oleg Nesterov
    Acked-by: Tejun Heo

    Oleg Nesterov
     
  • new_child->jobctl is not initialized during the fork, it is copied
    from parent->jobctl. Currently this is harmless, the forking task
    is running and copy_process() can't succeed if signal_pending() is
    true, so only JOBCTL_STOP_DEQUEUED can be copied. Still this is a
    bit fragile, it would be more clean to set ->jobctl = 0 explicitly.

    Also, check ->ptrace != 0 instead of PT_PTRACED, move the
    CONFIG_HAVE_HW_BREAKPOINT code up.

    Signed-off-by: Oleg Nesterov
    Acked-by: Tejun Heo

    Oleg Nesterov
     

28 Jun, 2011

1 commit

  • ptrace_reparented() naively does parent != real_parent, this means
    it returns true even if the tracer _is_ the real parent. This is per
    process thing, not per-thread. The only reason ->real_parent can
    point to the non-leader thread is that we have __WNOTHREAD.

    Change it to check !same_thread_group(parent, real_parent).

    It has two callers, and in both cases the current check does not
    look right.

    exit_notify: we should respect ->exit_signal if the exiting leader
    is traced by any thread from the parent thread group. It is the
    child of the whole group, and we are going to send the signal to
    the whole group.

    wait_task_zombie: without __WNOTHREAD do_wait() should do the same
    for any thread, only sys_ptrace() is "bound" to the single thread.
    However do_wait(WEXITED) succeeds but does not release a traced
    natural child unless the caller is the tracer.

    Test-case:

    void *tfunc(void *arg)
    {
    assert(ptrace(PTRACE_ATTACH, (long)arg, 0,0) == 0);
    pause();
    return NULL;
    }

    int main(void)
    {
    pthread_t thr;
    pid_t pid, stat, ret;

    pid = fork();
    if (!pid) {
    pause();
    assert(0);
    }

    assert(pthread_create(&thr, NULL, tfunc, (void*)(long)pid) == 0);

    assert(waitpid(-1, &stat, 0) == pid);
    assert(WIFSTOPPED(stat));

    kill(pid, SIGKILL);

    assert(waitpid(-1, &stat, 0) == pid);
    assert(WIFSIGNALED(stat) && WTERMSIG(stat) == SIGKILL);

    ret = waitpid(pid, &stat, 0);
    if (ret < 0)
    return 0;

    printf("WTF? %d is dead, but: wait=%d stat=%x\n",
    pid, ret, stat);

    return 1;
    }

    Note that the main thread simply does

    pid = fork();
    kill(pid, SIGKILL);

    and then without the patch wait4(WEXITED) succeeds twice and reports
    WTERMSIG(stat) == SIGKILL.

    Signed-off-by: Oleg Nesterov
    Acked-by: Tejun Heo

    Oleg Nesterov
     

23 Jun, 2011

4 commits

  • tracehook.h is on the way out. Rename tracehook_tracer_task() to
    ptrace_parent() and move it from tracehook.h to ptrace.h.

    Signed-off-by: Tejun Heo
    Cc: Christoph Hellwig
    Cc: John Johansen
    Cc: Stephen Smalley
    Signed-off-by: Oleg Nesterov

    Tejun Heo
     
  • Move SIGTRAP on exec(2) logic from tracehook_report_exec() to
    ptrace_event(). This is part of changes to make ptrace_event()
    smarter and handle ptrace event related details in one place.

    This doesn't introduce any behavior change.

    Signed-off-by: Tejun Heo
    Signed-off-by: Oleg Nesterov

    Tejun Heo
     
  • This patch implements ptrace_event_enabled() which tests whether a
    given PTRACE_EVENT_* is enabled and use it to simplify ptrace_event()
    and tracehook_prepare_clone().

    PT_EVENT_FLAG() macro is added which calculates PT_TRACE_* flag from
    PTRACE_EVENT_*. This is used to define PT_TRACE_* flags and by
    ptrace_event_enabled() to find the matching flag.

    This is used to make ptrace_event() and tracehook_prepare_clone()
    simpler.

    * ptrace_event() callers were responsible for providing mask to test
    whether the event was enabled. This patch implements
    ptrace_event_enabled() and make ptrace_event() drop @mask and
    determine whether the event is enabled from @event. Note that
    @event is constant and this conversion doesn't add runtime overhead.

    All conversions except tracehook_report_clone_complete() are
    trivial. tracehook_report_clone_complete() used to use 0 for @mask
    (always enabled) but now tests whether the specified event is
    enabled. This doesn't cause any behavior difference as it's
    guaranteed that the event specified by @trace is enabled.

    * tracehook_prepare_clone() now only determines which event is
    applicable and use ptrace_event_enabled() for enable test.

    This doesn't introduce any behavior change.

    Signed-off-by: Tejun Heo
    Signed-off-by: Oleg Nesterov

    Tejun Heo
     
  • task_ptrace(task) simply dereferences task->ptrace and isn't even used
    consistently only adding confusion. Kill it and directly access
    ->ptrace instead.

    This doesn't introduce any behavior change.

    Signed-off-by: Tejun Heo
    Signed-off-by: Oleg Nesterov

    Tejun Heo
     

17 Jun, 2011

3 commits

  • The previous patch implemented async notification for ptrace but it
    only worked while trace is running. This patch introduces
    PTRACE_LISTEN which is suggested by Oleg Nestrov.

    It's allowed iff tracee is in STOP trap and puts tracee into
    quasi-running state - tracee never really runs but wait(2) and
    ptrace(2) consider it to be running. While ptracer is listening,
    tracee is allowed to re-enter STOP to notify an async event.
    Listening state is cleared on the first notification. Ptracer can
    also clear it by issuing INTERRUPT - tracee will re-trap into STOP
    with listening state cleared.

    This allows ptracer to monitor group stop state without running tracee
    - use INTERRUPT to put tracee into STOP trap, issue LISTEN and then
    wait(2) to wait for the next group stop event. When it happens,
    PTRACE_GETSIGINFO provides information to determine the current state.

    Test program follows.

    #define PTRACE_SEIZE 0x4206
    #define PTRACE_INTERRUPT 0x4207
    #define PTRACE_LISTEN 0x4208

    #define PTRACE_SEIZE_DEVEL 0x80000000

    static const struct timespec ts1s = { .tv_sec = 1 };

    int main(int argc, char **argv)
    {
    pid_t tracee, tracer;
    int i;

    tracee = fork();
    if (!tracee)
    while (1)
    pause();

    tracer = fork();
    if (!tracer) {
    siginfo_t si;

    ptrace(PTRACE_SEIZE, tracee, NULL,
    (void *)(unsigned long)PTRACE_SEIZE_DEVEL);
    ptrace(PTRACE_INTERRUPT, tracee, NULL, NULL);
    repeat:
    waitid(P_PID, tracee, NULL, WSTOPPED);

    ptrace(PTRACE_GETSIGINFO, tracee, NULL, &si);
    if (!si.si_code) {
    printf("tracer: SIG %d\n", si.si_signo);
    ptrace(PTRACE_CONT, tracee, NULL,
    (void *)(unsigned long)si.si_signo);
    goto repeat;
    }
    printf("tracer: stopped=%d signo=%d\n",
    si.si_signo != SIGTRAP, si.si_signo);
    if (si.si_signo != SIGTRAP)
    ptrace(PTRACE_LISTEN, tracee, NULL, NULL);
    else
    ptrace(PTRACE_CONT, tracee, NULL, NULL);
    goto repeat;
    }

    for (i = 0; i < 3; i++) {
    nanosleep(&ts1s, NULL);
    printf("mother: SIGSTOP\n");
    kill(tracee, SIGSTOP);
    nanosleep(&ts1s, NULL);
    printf("mother: SIGCONT\n");
    kill(tracee, SIGCONT);
    }
    nanosleep(&ts1s, NULL);

    kill(tracer, SIGKILL);
    kill(tracee, SIGKILL);
    return 0;
    }

    This is identical to the program to test TRAP_NOTIFY except that
    tracee is PTRACE_LISTEN'd instead of PTRACE_CONT'd when group stopped.
    This allows ptracer to monitor when group stop ends without running
    tracee.

    # ./test-listen
    tracer: stopped=0 signo=5
    mother: SIGSTOP
    tracer: SIG 19
    tracer: stopped=1 signo=19
    mother: SIGCONT
    tracer: stopped=0 signo=5
    tracer: SIG 18
    mother: SIGSTOP
    tracer: SIG 19
    tracer: stopped=1 signo=19
    mother: SIGCONT
    tracer: stopped=0 signo=5
    tracer: SIG 18
    mother: SIGSTOP
    tracer: SIG 19
    tracer: stopped=1 signo=19
    mother: SIGCONT
    tracer: stopped=0 signo=5
    tracer: SIG 18

    -v2: Moved JOBCTL_LISTENING check in wait_task_stopped() into
    task_stopped_code() as suggested by Oleg.

    Signed-off-by: Tejun Heo
    Cc: Oleg Nesterov

    Tejun Heo
     
  • Currently, there's no way to trap a running ptracee short of sending a
    signal which has various side effects. This patch implements
    PTRACE_INTERRUPT which traps ptracee without any signal or job control
    related side effect.

    The implementation is almost trivial. It uses the group stop trap -
    SIGTRAP | PTRACE_EVENT_STOP << 8. A new trap flag
    JOBCTL_TRAP_INTERRUPT is added, which is set on PTRACE_INTERRUPT and
    cleared when any trap happens. As INTERRUPT should be useable
    regardless of the current state of tracee, task_is_traced() test in
    ptrace_check_attach() is skipped for INTERRUPT.

    PTRACE_INTERRUPT is available iff tracee is attached with
    PTRACE_SEIZE.

    Test program follows.

    #define PTRACE_SEIZE 0x4206
    #define PTRACE_INTERRUPT 0x4207

    #define PTRACE_SEIZE_DEVEL 0x80000000

    static const struct timespec ts100ms = { .tv_nsec = 100000000 };
    static const struct timespec ts1s = { .tv_sec = 1 };
    static const struct timespec ts3s = { .tv_sec = 3 };

    int main(int argc, char **argv)
    {
    pid_t tracee;

    tracee = fork();
    if (tracee == 0) {
    nanosleep(&ts100ms, NULL);
    while (1) {
    printf("tracee: alive pid=%d\n", getpid());
    nanosleep(&ts1s, NULL);
    }
    }

    if (argc > 1)
    kill(tracee, SIGSTOP);

    nanosleep(&ts100ms, NULL);

    ptrace(PTRACE_SEIZE, tracee, NULL,
    (void *)(unsigned long)PTRACE_SEIZE_DEVEL);
    if (argc > 1) {
    waitid(P_PID, tracee, NULL, WSTOPPED);
    ptrace(PTRACE_CONT, tracee, NULL, NULL);
    }
    nanosleep(&ts3s, NULL);

    printf("tracer: INTERRUPT and DETACH\n");
    ptrace(PTRACE_INTERRUPT, tracee, NULL, NULL);
    waitid(P_PID, tracee, NULL, WSTOPPED);
    ptrace(PTRACE_DETACH, tracee, NULL, NULL);
    nanosleep(&ts3s, NULL);

    printf("tracer: exiting\n");
    kill(tracee, SIGKILL);
    return 0;
    }

    When called without argument, tracee is seized from running state,
    interrupted and then detached back to running state.

    # ./test-interrupt
    tracee: alive pid=4546
    tracee: alive pid=4546
    tracee: alive pid=4546
    tracer: INTERRUPT and DETACH
    tracee: alive pid=4546
    tracee: alive pid=4546
    tracee: alive pid=4546
    tracer: exiting

    When called with argument, tracee is seized from stopped state,
    continued, interrupted and then detached back to stopped state.

    # ./test-interrupt 1
    tracee: alive pid=4548
    tracee: alive pid=4548
    tracee: alive pid=4548
    tracer: INTERRUPT and DETACH
    tracer: exiting

    Before PTRACE_INTERRUPT, once the tracee was running, there was no way
    to trap tracee and do PTRACE_DETACH without causing side effect.

    -v2: Updated to use task_set_jobctl_pending() so that it doesn't end
    up scheduling TRAP_STOP if child is dying which may make the
    child unkillable. Spotted by Oleg.

    Signed-off-by: Tejun Heo
    Cc: Oleg Nesterov

    Tejun Heo
     
  • PTRACE_ATTACH implicitly issues SIGSTOP on attach which has side
    effects on tracee signal and job control states. This patch
    implements a new ptrace request PTRACE_SEIZE which attaches a tracee
    without trapping it or affecting its signal and job control states.

    The usage is the same with PTRACE_ATTACH but it takes PTRACE_SEIZE_*
    flags in @data. Currently, the only defined flag is
    PTRACE_SEIZE_DEVEL which is a temporary flag to enable PTRACE_SEIZE.
    PTRACE_SEIZE will change ptrace behaviors outside of attach itself.
    The changes will be implemented gradually and the DEVEL flag is to
    prevent programs which expect full SEIZE behavior from using it before
    all the behavior modifications are complete while allowing unit
    testing. The flag will be removed once SEIZE behaviors are completely
    implemented.

    * PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
    attaching tracee continues to run unless a trap condition occurs.

    * PTRACE_SEIZE doesn't affect signal or group stop state.

    * If PTRACE_SEIZE'd, group stop uses PTRACE_EVENT_STOP trap which uses
    exit_code of (signr | PTRACE_EVENT_STOP << 8) where signr is one of
    the stopping signals if group stop is in effect or SIGTRAP
    otherwise, and returns usual trap siginfo on PTRACE_GETSIGINFO
    instead of NULL.

    Seizing sets PT_SEIZED in ->ptrace of the tracee. This flag will be
    used to determine whether new SEIZE behaviors should be enabled.

    Test program follows.

    #define PTRACE_SEIZE 0x4206
    #define PTRACE_SEIZE_DEVEL 0x80000000

    static const struct timespec ts100ms = { .tv_nsec = 100000000 };
    static const struct timespec ts1s = { .tv_sec = 1 };
    static const struct timespec ts3s = { .tv_sec = 3 };

    int main(int argc, char **argv)
    {
    pid_t tracee;

    tracee = fork();
    if (tracee == 0) {
    nanosleep(&ts100ms, NULL);
    while (1) {
    printf("tracee: alive\n");
    nanosleep(&ts1s, NULL);
    }
    }

    if (argc > 1)
    kill(tracee, SIGSTOP);

    nanosleep(&ts100ms, NULL);

    ptrace(PTRACE_SEIZE, tracee, NULL,
    (void *)(unsigned long)PTRACE_SEIZE_DEVEL);
    if (argc > 1) {
    waitid(P_PID, tracee, NULL, WSTOPPED);
    ptrace(PTRACE_CONT, tracee, NULL, NULL);
    }
    nanosleep(&ts3s, NULL);
    printf("tracer: exiting\n");
    return 0;
    }

    When the above program is called w/o argument, tracee is seized while
    running and remains running. When tracer exits, tracee continues to
    run and print out messages.

    # ./test-seize-simple
    tracee: alive
    tracee: alive
    tracee: alive
    tracer: exiting
    tracee: alive
    tracee: alive

    When called with an argument, tracee is seized from stopped state and
    continued, and returns to stopped state when tracer exits.

    # ./test-seize
    tracee: alive
    tracee: alive
    tracee: alive
    tracer: exiting
    # ps -el|grep test-seize
    1 T 0 4720 1 0 80 0 - 941 signal ttyS0 00:00:00 test-seize

    -v2: SEIZE doesn't schedule TRAP_STOP and leaves tracee running as Jan
    suggested.

    -v3: PTRACE_EVENT_STOP traps now report group stop state by signr. If
    group stop is in effect the stop signal number is returned as
    part of exit_code; otherwise, SIGTRAP. This was suggested by
    Denys and Oleg.

    Signed-off-by: Tejun Heo
    Cc: Jan Kratochvil
    Cc: Denys Vlasenko
    Cc: Oleg Nesterov

    Tejun Heo
     

05 Jun, 2011

1 commit


25 Apr, 2011

1 commit

  • When a task is traced and is in a stopped state, the tracer
    may execute a ptrace request to examine the tracee state and
    get its task struct. Right after, the tracee can be killed
    and thus its breakpoints released.
    This can happen concurrently when the tracer is in the middle
    of reading or modifying these breakpoints, leading to dereferencing
    a freed pointer.

    Hence, to prepare the fix, create a generic breakpoint reference
    holding API. When a reference on the breakpoints of a task is
    held, the breakpoints won't be released until the last reference
    is dropped. After that, no more ptrace request on the task's
    breakpoints can be serviced for the tracer.

    Reported-by: Oleg Nesterov
    Signed-off-by: Frederic Weisbecker
    Cc: Ingo Molnar
    Cc: Peter Zijlstra
    Cc: Will Deacon
    Cc: Prasad
    Cc: Paul Mundt
    Cc: v2.6.33..
    Link: http://lkml.kernel.org/r/1302284067-7860-2-git-send-email-fweisbec@gmail.com

    Frederic Weisbecker
     

05 Mar, 2011

1 commit


28 Oct, 2010

2 commits

  • Fix up the arguments to arch_ptrace() to take account of the fact that
    @addr and @data are now unsigned long rather than long as of a preceding
    patch in this series.

    Signed-off-by: Namhyung Kim
    Cc:
    Acked-by: Roland McGrath
    Acked-by: David Howells
    Acked-by: Geert Uytterhoeven
    Acked-by: David S. Miller
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Namhyung Kim
     
  • Since userspace API of ptrace syscall defines @addr and @data as void
    pointers, it would be more appropriate to define them as unsigned long in
    kernel. Therefore related functions are changed also.

    'unsigned long' is typically used in other places in kernel as an opaque
    data type and that using this helps cleaning up a lot of warnings from
    sparse.

    Suggested-by: Arnd Bergmann
    Signed-off-by: Namhyung Kim
    Acked-by: Arnd Bergmann
    Acked-by: Roland McGrath
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Namhyung Kim
     

26 Mar, 2010

1 commit

  • Support for the PMU's BTS features has been upstreamed in
    v2.6.32, but we still have the old and disabled ptrace-BTS,
    as Linus noticed it not so long ago.

    It's buggy: TIF_DEBUGCTLMSR is trampling all over that MSR without
    regard for other uses (perf) and doesn't provide the flexibility
    needed for perf either.

    Its users are ptrace-block-step and ptrace-bts, since ptrace-bts
    was never used and ptrace-block-step can be implemented using a
    much simpler approach.

    So axe all 3000 lines of it. That includes the *locked_memory*()
    APIs in mm/mlock.c as well.

    Reported-by: Linus Torvalds
    Signed-off-by: Peter Zijlstra
    Cc: Roland McGrath
    Cc: Oleg Nesterov
    Cc: Markus Metzger
    Cc: Steven Rostedt
    Cc: Andrew Morton
    LKML-Reference:
    Signed-off-by: Ingo Molnar

    Peter Zijlstra
     

13 Mar, 2010

1 commit

  • While in theory user_enable_single_step/user_disable_single_step/
    user_enable_blockstep could also be provided as an inline or macro there's
    no good reason to do so, and having the prototype in one places keeps code
    size and confusion down.

    Roland said:

    The original thought there was that user_enable_single_step() et al
    might well be only an instruction or three on a sane machine (as if we
    have any of those!), and since there is only one call site inlining
    would be beneficial. But I agree that there is no strong reason to care
    about inlining it.

    As to the arch changes, there is only one thought I'd add to the
    record. It was always my thinking that for an arch where
    PTRACE_SINGLESTEP does text-modifying breakpoint insertion,
    user_enable_single_step() should not be provided. That is,
    arch_has_single_step()=>true means that there is an arch facility with
    "pure" semantics that does not have any unexpected side effects.
    Inserting a breakpoint might do very unexpected strange things in
    multi-threaded situations. Aside from that, it is a peculiar side
    effect that user_{enable,disable}_single_step() should cause COW
    de-sharing of text pages and so forth. For PTRACE_SINGLESTEP, all these
    peculiarities are the status quo ante for that arch, so having
    arch_ptrace() itself do those is one thing. But for building other
    things in the future, it is nicer to have a uniform "pure" semantics
    that arch-independent code can expect.

    OTOH, all such arch issues are really up to the arch maintainer. As
    of today, there is nothing but ptrace using user_enable_single_step() et
    al so it's a distinction without a practical difference. If/when there
    are other facilities that use user_enable_single_step() and might care,
    the affected arch's can revisit the question when someone cares about
    the quality of the arch support for said new facility.

    Signed-off-by: Christoph Hellwig
    Cc: Oleg Nesterov
    Cc: Roland McGrath
    Acked-by: David Howells
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Hellwig
     

24 Feb, 2010

1 commit


12 Feb, 2010

1 commit

  • Generic support for PTRACE_GETREGSET/PTRACE_SETREGSET commands which
    export the regsets supported by each architecture using the correponding
    NT_* types. These NT_* types are already part of the userland ABI, used
    in representing the architecture specific register sets as different NOTES
    in an ELF core file.

    'addr' parameter for the ptrace system call encode the REGSET type (using
    the corresppnding NT_* type) and the 'data' parameter points to the
    struct iovec having the user buffer and the length of that buffer.

    struct iovec iov = { buf, len};
    ret = ptrace(PTRACE_GETREGSET/PTRACE_SETREGSET, pid, NT_XXX_TYPE, &iov);

    On successful completion, iov.len will be updated by the kernel specifying
    how much the kernel has written/read to/from the user's iov.buf.

    x86 extended state registers are primarily exported using this interface.

    Signed-off-by: Suresh Siddha
    LKML-Reference:
    Acked-by: Hongjiu Lu
    Cc: Roland McGrath
    Signed-off-by: H. Peter Anvin

    Suresh Siddha
     

16 Dec, 2009

2 commits

  • Suggested by Roland.

    Currently there is no way to synthesize a single-stepping trap in the
    arch-independent manner. This patch adds the default helper which fills
    siginfo_t, arch/ can can override it.

    Architetures which implement user_enable_single_step() should add
    user_single_step_siginfo() also.

    Signed-off-by: Oleg Nesterov
    Acked-by: Roland McGrath
    Cc:
    Cc: Ingo Molnar
    Cc: Thomas Gleixner
    Cc: "H. Peter Anvin"
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Oleg Nesterov
     
  • No functional changes.

    ptrace_init_task() looks confusing, as if we always auto-attach when "bool
    ptrace" argument is true, while in fact we attach only if current is
    traced.

    Make the code more explicit and kill now unused ptrace_link().

    Signed-off-by: Oleg Nesterov
    Acked-by: Roland McGrath
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Oleg Nesterov
     

19 Jun, 2009

1 commit

  • - Use rcu_read_lock() instead of tasklist_lock to find/get the task
    in ptrace_get_task_struct().

    - Make it static, it has no callers outside of ptrace.c.

    - The comment doesn't match the reality, this helper does not do
    any checks. Beacuse it is really trivial and static I removed the
    whole comment.

    Signed-off-by: Oleg Nesterov
    Acked-by: Roland McGrath
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Oleg Nesterov
     

07 Apr, 2009

1 commit

  • Add the ptrace bts context field to task_struct unconditionally.

    Initialize the field directly in copy_process().
    Remove all the unneeded functionality used to initialize that field.

    Signed-off-by: Markus Metzger
    Cc: roland@redhat.com
    Cc: eranian@googlemail.com
    Cc: oleg@redhat.com
    Cc: juan.villacis@intel.com
    Cc: ak@linux.jf.intel.com
    LKML-Reference:
    Signed-off-by: Ingo Molnar

    Markus Metzger
     

03 Apr, 2009

2 commits

  • By discussion with Roland.

    - Rename ptrace_exit() to exit_ptrace(), and change it to do all the
    necessary work with ->ptraced list by its own.

    - Move this code from exit.c to ptrace.c

    - Update the comment in ptrace_detach() to explain the rechecking of
    the child->ptrace.

    Signed-off-by: Oleg Nesterov
    Cc: "Eric W. Biederman"
    Cc: "Metzger, Markus T"
    Cc: Roland McGrath
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Oleg Nesterov
     
  • When ptrace_detach() takes tasklist, the tracee can be SIGKILL'ed. If it
    has already passed exit_notify() we can leak a zombie, because a) ptracing
    disables the auto-reaping logic, and b) ->real_parent was not notified
    about the child's death.

    ptrace_detach() should follow the ptrace_exit's logic, change the code
    accordingly.

    Signed-off-by: Oleg Nesterov
    Cc: Jerome Marchand
    Cc: Roland McGrath
    Tested-by: Denys Vlasenko
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Oleg Nesterov
     

20 Dec, 2008

1 commit

  • Impact: introduce new ptrace facility

    Add arch_ptrace_untrace() function that is called when the tracer
    detaches (either voluntarily or when the tracing task dies);
    ptrace_disable() is only called on a voluntary detach.

    Add ptrace_fork() and arch_ptrace_fork(). They are called when a
    traced task is forked.

    Clear DS and BTS related fields on fork.

    Release DS resources and reclaim memory in ptrace_untrace(). This
    releases resources already when the tracing task dies. We used to do
    that when the traced task dies.

    Signed-off-by: Markus Metzger
    Signed-off-by: Ingo Molnar

    Markus Metzger
     

20 Oct, 2008

1 commit


08 Aug, 2008

1 commit

  • In the change in commit 09a05394fe2448a4139b014936330af23fa7ec83, I
    overlooked two nits in the logic and this broke using CLONE_PTRACE
    when PTRACE_O_TRACE* are not being used.

    A parent that is itself traced at all but not using PTRACE_O_TRACE*,
    using CLONE_PTRACE would have its new child fail to be traced.

    A parent that is not itself traced at all that uses CLONE_PTRACE
    (which should be a no-op in this case) would confuse the bookkeeping
    and lead to a crash at exit time.

    This restores the missing checks and fixes both failure modes.

    Reported-by: Eduardo Habkost
    Signed-off-by: Roland McGrath

    Roland McGrath
     

27 Jul, 2008

4 commits

  • This adds the new function task_current_syscall() on machines where the
    asm/syscall.h interface is supported (CONFIG_HAVE_ARCH_TRACEHOOK). It's
    exported for modules to use in the future. This function safely samples
    the state of a blocked thread to collect what system call it is blocked
    in, and the six system call argument registers.

    Signed-off-by: Roland McGrath
    Cc: Oleg Nesterov
    Reviewed-by: Ingo Molnar
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Roland McGrath
     
  • This moves the ptrace-related logic from release_task into tracehook.h and
    ptrace.h inlines. It provides clean hooks both before and after locking
    tasklist_lock, for future tracing logic to do more cleanup without the
    lock.

    This also changes release_task() itself in the rare "zap_leader" case to
    set the leader to EXIT_DEAD before iterating. This maintains the
    invariant that release_task() only ever handles a task in EXIT_DEAD. This
    is a common-sense invariant that is already always true except in this one
    arcane case of zombie leader whose parent ignores SIGCHLD.

    This change is harmless and only costs one store in this one rare case.
    It keeps the expected state more consisently sane, which is nicer when
    debugging weirdness in release_task(). It also lets some future code in
    the tracehook entry points rely on this invariant for bookkeeping.

    Signed-off-by: Roland McGrath
    Cc: Oleg Nesterov
    Reviewed-by: Ingo Molnar
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Roland McGrath
     
  • This moves all the ptrace initialization and tracing logic for task
    creation into tracehook.h and ptrace.h inlines. It reorganizes the code
    slightly, but should not change any behavior.

    There are four tracehook entry points, at each important stage of task
    creation. This keeps the interface from the core fork.c code fairly
    clean, while supporting the complex setup required for ptrace or something
    like it.

    Signed-off-by: Roland McGrath
    Cc: Oleg Nesterov
    Reviewed-by: Ingo Molnar
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Roland McGrath
     
  • This patch series introduces the "tracehook" interface layer of inlines in
    . There are more details in the log entry for patch
    01/23 and in the header file comments inside that patch. Most of these
    changes move code around with little or no change, and they should not
    break anything or change any behavior.

    This sets a new standard for uniform arch support to enable clean
    arch-independent implementations of new debugging and tracing stuff,
    denoted by CONFIG_HAVE_ARCH_TRACEHOOK. Patch 20/23 adds that symbol to
    arch/Kconfig, with comments listing everything an arch has to do before
    setting "select HAVE_ARCH_TRACEHOOK". These are elaborted a bit at:

    http://sourceware.org/systemtap/wiki/utrace/arch/HowTo

    The new inlines that arch code must define or call have detailed kerneldoc
    comments in the generic header files that say what is required.

    No arch is obligated to do any work, and no arch's build should be broken
    by these changes. There are several steps that each arch should take so
    it can set HAVE_ARCH_TRACEHOOK. Most of these are simple. Providing this
    support will let new things people add for doing debugging and tracing of
    user-level threads "just work" for your arch in the future. For an arch
    that does not provide HAVE_ARCH_TRACEHOOK, some new options for such
    features will not be available for config.

    I have done some arch work and will submit this to the arch maintainers
    after the generic tracehook series settles in. For now, that work is
    available in my GIT repositories, and in patch and mbox-of-patches form at
    http://people.redhat.com/roland/utrace/2.6-current/

    This paves the way for my "utrace" work, to be submitted later. But it is
    not innately tied to that. I hope that the tracehook series can go in
    soon regardless of what eventually does or doesn't go on top of it. For
    anyone implementing any kind of new tracing/debugging plan, or just
    understanding all the context of the existing ptrace implementation,
    having tracehook.h makes things much easier to find and understand.

    This patch:

    This adds the new kernel-internal header file . This
    is not yet used at all. The comments in the header introduce what the
    following series of patches is about.

    The aim is to formalize and consolidate all the places that the core
    kernel code and the arch code now ties into the ptrace implementation.

    These patches mostly don't cause any functional change. They just move
    the details of ptrace logic out of core code into tracehook.h inlines,
    where they are mostly compiled away to the same as before. All that
    changes is that everything is thoroughly documented and any future
    reworking of ptrace, or addition of something new, would not have to touch
    core code all over, just change the tracehook.h inlines.

    The new linux/ptrace.h inlines are used by the following patches in the
    new tracehook_*() inlines. Using these helpers for the ptrace event stops
    makes it simple to change or disable the old ptrace implementation of
    these stops conditionally later.

    Signed-off-by: Roland McGrath
    Cc: Oleg Nesterov
    Reviewed-by: Ingo Molnar
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Roland McGrath
     

14 Jul, 2008

1 commit

  • Enable security modules to distinguish reading of process state via
    proc from full ptrace access by renaming ptrace_may_attach to
    ptrace_may_access and adding a mode argument indicating whether only
    read access or full attach access is requested. This allows security
    modules to permit access to reading process state without granting
    full ptrace access. The base DAC/capability checking remains unchanged.

    Read access to /proc/pid/mem continues to apply a full ptrace attach
    check since check_mem_permission() already requires the current task
    to already be ptracing the target. The other ptrace checks within
    proc for elements like environ, maps, and fds are changed to pass the
    read mode instead of attach.

    In the SELinux case, we model such reading of process state as a
    reading of a proc file labeled with the target process' label. This
    enables SELinux policy to permit such reading of process state without
    permitting control or manipulation of the target process, as there are
    a number of cases where programs probe for such information via proc
    but do not need to be able to control the target (e.g. procps,
    lsof, PolicyKit, ConsoleKit). At present we have to choose between
    allowing full ptrace in policy (more permissive than required/desired)
    or breaking functionality (or in some cases just silencing the denials
    via dontaudit rules but this can hide genuine attacks).

    This version of the patch incorporates comments from Casey Schaufler
    (change/replace existing ptrace_may_attach interface, pass access
    mode), and Chris Wright (provide greater consistency in the checking).

    Note that like their predecessors __ptrace_may_attach and
    ptrace_may_attach, the __ptrace_may_access and ptrace_may_access
    interfaces use different return value conventions from each other (0
    or -errno vs. 1 or 0). I retained this difference to avoid any
    changes to the caller logic but made the difference clearer by
    changing the latter interface to return a bool rather than an int and
    by adding a comment about it to ptrace.h for any future callers.

    Signed-off-by: Stephen Smalley
    Acked-by: Chris Wright
    Signed-off-by: James Morris

    Stephen Smalley
     

30 Apr, 2008

1 commit

  • Add another trivial helper for the sake of grep. It also auto-documents the
    fact that ->parent != real_parent implies ->ptrace.

    No functional changes.

    Signed-off-by: Oleg Nesterov
    Acked-by: Roland McGrath
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Oleg Nesterov
     

09 Feb, 2008

1 commit

  • Since the patch

    "Fix ptrace_attach()/ptrace_traceme()/de_thread() race"
    commit f5b40e363ad6041a96e3da32281d8faa191597b9

    we set PT_ATTACHED and change child->parent "atomically" wrt task_list lock.

    This means we can remove the checks like "PT_ATTACHED && ->parent != ptracer"
    which were needed to catch the "ptrace attach is in progress" case. We can
    also remove the flag itself since nobody else uses it.

    Signed-off-by: Oleg Nesterov
    Acked-by: Roland McGrath
    Cc: Christoph Hellwig
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Oleg Nesterov
     

07 Feb, 2008

1 commit

  • This adds support to allow asm/ptrace.h to define two new macros,
    arch_ptrace_stop_needed and arch_ptrace_stop. These control special
    machine-specific actions to be done before a ptrace stop. The new code
    compiles away to nothing when the new macros are not defined. This is the
    case on all machines to begin with.

    On ia64, these macros will be defined to solve the long-standing issue of
    ptrace vs register backing store.

    Signed-off-by: Roland McGrath
    Cc: Petr Tesarik
    Cc: Tony Luck
    Cc: Matthew Wilcox
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Roland McGrath
     

30 Jan, 2008

2 commits

  • This makes ptrace_request handle PTRACE_SINGLEBLOCK along with
    PTRACE_CONT et al. The new generic code makes use of the
    arch_has_block_step macro and generic entry points on machines
    that define them.

    [ mingo@elte.hu: bugfix ]

    Signed-off-by: Roland McGrath
    Signed-off-by: Ingo Molnar
    Signed-off-by: Thomas Gleixner

    Roland McGrath
     
  • This defines the new macro arch_has_block_step() in linux/ptrace.h, a
    default for when asm/ptrace.h does not define it. This is the analog
    of arch_has_single_step() for step-until-branch on machines that have
    it. It declares the new user_enable_block_step function, which goes
    with the existing user_enable_single_step and user_disable_single_step.
    This is not used yet, but paves the way to harmonize on this interface
    for the arch-specific calls on all machines.

    Signed-off-by: Roland McGrath
    Signed-off-by: Ingo Molnar
    Signed-off-by: Thomas Gleixner

    Roland McGrath