lkml.org 
[lkml]   [2000]   [Feb]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[PATCH] subterfugue-ptrace patch #1 (was Re: vfork)
    From
    Date
    Linus Torvalds <torvalds@transmeta.com> writes:
    > On 24 Dec 1999, Mike Coleman wrote:
    > > I didn't see anyone comment, so I will. I'd like to see this change go in for
    > > 2.4. Without it, CLONE_PTRACE is not very useful.
    >
    > If you can show that it works, and that you can strace a vfork() and over
    > a clone(), then send me the patch and I'll apply it in a jiffy. I'd like
    > to hear that it actually _does_ work in real life, and I'd be even happier
    > if I'd see a working "strace" as a result. Ok?


    Ok. SUBTERFUGUE, which I just posted an announcment for, demonstrates process
    following over vfork and clone. The patch it uses is pretty similar to what
    was being discussed here in December, but adds a couple of things. Here is a
    description of the patch (from http://subterfugue.org/patches.html). The
    patch itself, against 2.3.42, is appended below.

    (Sorry, I don't have a working strace, but I believe the same techniques used
    in SUBTERFUGUE will also work for strace. I'll happily render any needed
    assistance to make that happen.)

    --Mike


    ------------------------------------------------------------------------------

    Here are the changes included in the patch. Most are fairly innocuous
    extensions, but the first two might break some things.

    1. The exit_code reported during PTRACE_SYSCALL stops now has its high bit
    (0x80) set, to distinguish it from signal stops. Unfortunately, this
    breaks strace, and probably any other program that uses PTRACE_SYSCALL
    (see ptrace(2)). The fix is pretty simple--just mask off the high bit
    (or adapt the program to make use of the extra information). A patch is
    available that does this for strace. (It doesn't appear that gdb is
    affected.)
    2. When a new child is created with clone and CLONE_PARENT is set, and the
    child is being traced (e.g., it's done a PTRACE_TRACEME), it will now
    report to the first process' parent. This is correct behavior, but it
    opens up what some would consider a security hole--a malicious child
    might unexpectedly invoke PTRACE_TRACEME, causing it to report to a
    waiting parent process that never expected to hear from it. This was
    discussed on linux-kernel for a bit; there didn't seem to be a
    consensus about whether this was even a hole at all.
    3. A new wait flag __WALL is implemented, to allow clone and non-clone
    children to be waited for simultaneously.
    4. A new ptrace command PTRACE_GETPPID is implemented, which lets a
    tracing process discover the original parent of a traced child. This
    information is otherwise unavailable.
    5. Exits of the system calls fork, vfork, and clone are now reported.

    ------------------------------------------------------------------------------

    --- linux-2.3.42/kernel/exit.c.orig Sat Feb 5 02:08:19 2000
    +++ linux-2.3.42/kernel/exit.c Sat Feb 5 02:09:32 2000
    @@ -445,7 +445,7 @@
    DECLARE_WAITQUEUE(wait, current);
    struct task_struct *p;

    - if (options & ~(WNOHANG|WUNTRACED|__WCLONE))
    + if (options & ~(WNOHANG|WUNTRACED|__WCLONE|__WALL))
    return -EINVAL;

    add_wait_queue(&current->wait_chldexit,&wait);
    @@ -464,8 +464,13 @@
    if (p->pgrp != -pid)
    continue;
    }
    - /* wait for cloned processes iff the __WCLONE flag is set */
    - if ((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0))
    + /* Wait for all children (clone and not) if __WALL is set;
    + * otherwise, wait for clone children *only* if __WCLONE is
    + * set; otherwise, wait for non-clone children *only*. (Note:
    + * A "clone" child here is one that reports to its parent
    + * using a signal other than SIGCHLD.) */
    + if (((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0))
    + && !(options & __WALL))
    continue;
    flag = 1;
    switch (p->state) {
    --- linux-2.3.42/kernel/fork.c.orig Mon Dec 13 17:39:24 1999
    +++ linux-2.3.42/kernel/fork.c Sat Feb 5 02:09:32 2000
    @@ -646,8 +646,11 @@
    p->run_list.next = NULL;
    p->run_list.prev = NULL;

    - if ((clone_flags & CLONE_VFORK) || !(clone_flags & CLONE_PARENT))
    - p->p_pptr = p->p_opptr = current;
    + if ((clone_flags & CLONE_VFORK) || !(clone_flags & CLONE_PARENT)) {
    + p->p_opptr = current;
    + if (!(current->flags & PF_PTRACED))
    + p->p_pptr = current;
    + }
    p->p_cptr = NULL;
    init_waitqueue_head(&p->wait_chldexit);
    p->vfork_sem = NULL;
    --- linux-2.3.42/include/linux/wait.h.orig Mon Jan 10 20:29:12 2000
    +++ linux-2.3.42/include/linux/wait.h Sat Feb 5 02:09:32 2000
    @@ -4,6 +4,7 @@
    #define WNOHANG 0x00000001
    #define WUNTRACED 0x00000002

    +#define __WALL 0x40000000
    #define __WCLONE 0x80000000

    #ifdef __KERNEL__
    --- linux-2.3.42/include/asm-i386/ptrace.h.orig Tue Dec 9 19:57:09 1997
    +++ linux-2.3.42/include/asm-i386/ptrace.h Sat Feb 5 02:09:32 2000
    @@ -47,6 +47,8 @@
    #define PTRACE_GETFPREGS 14
    #define PTRACE_SETFPREGS 15

    +#define PTRACE_GETPPID 20
    +
    #ifdef __KERNEL__
    #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
    #define instruction_pointer(regs) ((regs)->eip)
    --- linux-2.3.42/arch/i386/kernel/entry.S.orig Sat Feb 5 02:07:42 2000
    +++ linux-2.3.42/arch/i386/kernel/entry.S Sat Feb 5 02:09:32 2000
    @@ -180,6 +180,8 @@
    call SYMBOL_NAME(schedule_tail)
    addl $4, %esp
    GET_CURRENT(%ebx)
    + testb $0x20,flags(%ebx) # PF_TRACESYS
    + jne tracesys_exit # need to set eax first??
    jmp ret_from_sys_call

    /*
    --- linux-2.3.42/arch/i386/kernel/ptrace.c.orig Sat Feb 5 02:07:22 2000
    +++ linux-2.3.42/arch/i386/kernel/ptrace.c Sat Feb 5 02:11:27 2000
    @@ -431,6 +431,12 @@
    break;
    }

    + case PTRACE_GETPPID: { /* Who's your daddy? */
    + unsigned long ppid = child->p_opptr->pid;
    + ret = put_user(ppid, (unsigned long *) data);
    + break;
    + }
    +
    default:
    ret = -EIO;
    break;
    @@ -445,7 +451,7 @@
    if ((current->flags & (PF_PTRACED|PF_TRACESYS))
    != (PF_PTRACED|PF_TRACESYS))
    return;
    - current->exit_code = SIGTRAP;
    + current->exit_code = SIGTRAP | 0x80;
    current->state = TASK_STOPPED;
    notify_parent(current, SIGCHLD);
    schedule();

    --
    Any sufficiently adverse technology is indistinguishable from Microsoft.

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.rutgers.edu
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-03-22 13:56    [W:0.025 / U:75.536 seconds]
    ©2003-2017 Jasper Spaans. hosted at Digital OceanAdvertise on this site