Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 3 Apr 2013 19:05:18 -0700
From:      Brian Demsky <bdemsky@uci.edu>
To:        freebsd-bugs@freebsd.org
Subject:   Bug in swapcontext method
Message-ID:  <F99A8507-A452-4FFD-BC73-544578DE812D@uci.edu>

next in thread | raw e-mail | index | archive | help
Here is the code for swap context:

int
swapcontext(ucontext_t *oucp, const ucontext_t *ucp)
{
        int ret;

        if ((oucp =3D=3D NULL) || (ucp =3D=3D NULL)) {
                errno =3D EINVAL;
                return (-1);
        }
        oucp->uc_flags &=3D ~UCF_SWAPPED;
        ret =3D getcontext(oucp);
        if ((ret =3D=3D 0) && !(oucp->uc_flags & UCF_SWAPPED)) {
                oucp->uc_flags |=3D UCF_SWAPPED;
                ret =3D setcontext(ucp);
        }
        return (ret);
}

On the OS X port of libc, this gets compiled as:

0x00007fff901e86b2 <swapcontext+0>:     push   %r14
0x00007fff901e86b4 <swapcontext+2>:     push   %rbx
0x00007fff901e86b5 <swapcontext+3>:     sub    $0x8,%rsp
0x00007fff901e86b9 <swapcontext+7>:     test   %rdi,%rdi
0x00007fff901e86bc <swapcontext+10>:    je     0x7fff901e86c6 =
<swapcontext+20>
0x00007fff901e86be <swapcontext+12>:    mov    %rsi,%rbx
0x00007fff901e86c1 <swapcontext+15>:    test   %rbx,%rbx
0x00007fff901e86c4 <swapcontext+18>:    jne    0x7fff901e86d8 =
<swapcontext+38>
0x00007fff901e86c6 <swapcontext+20>:    callq  0x7fff90262c88 <__error>
0x00007fff901e86cb <swapcontext+25>:    movl   $0x16,(%rax)
0x00007fff901e86d1 <swapcontext+31>:    mov    $0xffffffff,%eax
0x00007fff901e86d6 <swapcontext+36>:    jmp    0x7fff901e86f3 =
<swapcontext+65>
0x00007fff901e86d8 <swapcontext+38>:    mov    %rdi,%r14
0x00007fff901e86db <swapcontext+41>:    andb   $0x7f,0x3(%r14)
0x00007fff901e86e0 <swapcontext+46>:    mov    %r14,%rdi
0x00007fff901e86e3 <swapcontext+49>:    callq  0x7fff901e87af =
<getcontext>
0x00007fff901e86e8 <swapcontext+54>:    test   %eax,%eax
0x00007fff901e86ea <swapcontext+56>:    jne    0x7fff901e86f3 =
<swapcontext+65>
0x00007fff901e86ec <swapcontext+58>:    mov    (%r14),%ecx
0x00007fff901e86ef <swapcontext+61>:    test   %ecx,%ecx
0x00007fff901e86f1 <swapcontext+63>:    jns    0x7fff901e86fb =
<swapcontext+73>
0x00007fff901e86f3 <swapcontext+65>:    add    $0x8,%rsp
0x00007fff901e86f7 <swapcontext+69>:    pop    %rbx
0x00007fff901e86f8 <swapcontext+70>:    pop    %r14
0x00007fff901e86fa <swapcontext+72>:    retq  =20
0x00007fff901e86fb <swapcontext+73>:    or     $0x80000000,%ecx
0x00007fff901e8701 <swapcontext+79>:    mov    %ecx,(%r14)
0x00007fff901e8704 <swapcontext+82>:    mov    %rbx,%rdi
0x00007fff901e8707 <swapcontext+85>:    add    $0x8,%rsp
0x00007fff901e870b <swapcontext+89>:    pop    %rbx
0x00007fff901e870c <swapcontext+90>:    pop    %r14
0x00007fff901e870e <swapcontext+92>:    jmpq   0x7fff90262855 =
<setcontext>

The problem is that rbx is callee saved by compiled version of =
swapcontext and then reused before getcontext is called.  Getcontext =
then stores the wrong value for rbx and setcontext later restores the =
wrong value for rbx.  If the caller had any value in rbx, it has been =
trashed at this point.

Brian=



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?F99A8507-A452-4FFD-BC73-544578DE812D>