https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61118

Florian Weimer <fw at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|[6/7/8 Regression] Spurious |[6/7/8 Regression] Indirect
                   |-Wclobbered warning         |call generated for
                   |generated by gcc 4.9.0 for  |pthread_cleanup_push with
                   |pthread_cleanup_push        |constant cleanup function

--- Comment #13 from Florian Weimer <fw at gcc dot gnu.org> ---
This is not simply a spurious warning (the variables in question are only
assigned once and their address is not taken, so C semantics do not allow that
they are clobbered by setjmp+longjmp).

I compiled the reproducer with

    pthread_cleanup_pop(1);

to see the cleanup action on the non-cancellation path, too.  All compilation
with -fpic to avoid yet another GCC 7 weirdness (movl $cleanup_fn; %eax, call
*%rax).

GCC 4.8.5 20150623 (Red Hat 4.8.5-22) produces:

        call    pthread_cond_wait@PLT
        movq    %r14, %rdi
        call    __pthread_unregister_cancel@PLT
        movq    %rbx, %rdi
        call    cleanup_fn@PLT

GCC 7.2.1 20170829 (Red Hat 7.2.1-1) gives me:

        movq    cleanup_fn@GOTPCREL(%rip), %rax
        movq    %rax, 32(%rsp)
…
        call    pthread_cond_wait@PLT
        movq    %rbx, %rdi
        call    __pthread_unregister_cancel@PLT
        movq    32(%rsp), %rax
        movq    40(%rsp), %rdi
        call    *%rax

This is quite unsatisfying from a security hardening point of view because we
now have an unencrypted function pointer on the stack.  This situation is
somewhat analogous to Windows SEH, which turned out very problematic.  (The
jmp_buf on the stack isn't ideal, but at least the PC value in it is mangled.)

Reply via email to