mbox series

[0/4] Restartable Sequences support for glibc 2.30

Message ID 20190212194253.1951-1-mathieu.desnoyers@efficios.com
Headers show
Series Restartable Sequences support for glibc 2.30 | expand

Message

Mathieu Desnoyers Feb. 12, 2019, 7:42 p.m. UTC
Hi,

This patchset implements basic support for the "rseq" Linux system call
in glibc by registering the rseq TLS abi.

One patch in this series modifies sched_getcpu() to speed up reading the
current CPU number by reading __rseq_abi.cpu_id when rseq is available.

The only point that still appears to not reach concensus is whether it's
acceptable to define the RSEQ_SIG code signature for each architecture.
If I missed other points that failed to reach concensus, please let me
know!

Please consider for inclusion into glibc,

Thanks,

Mathieu


Mathieu Desnoyers (4):
  glibc: Perform rseq(2) registration at C startup and thread creation
    (v7)
  glibc: sched_getcpu(): use rseq cpu_id TLS on Linux
  support record failure: allow use from constructor
  rseq registration tests (v2)

 NEWS                                          |  11 +
 csu/libc-start.c                              |  12 +-
 misc/Makefile                                 |   3 +-
 misc/rseq-internal.h                          |  34 ++
 nptl/pthread_create.c                         |   9 +
 support/check.h                               |   4 +
 support/support_record_failure.c              |  18 +-
 sysdeps/unix/sysv/linux/Makefile              |   8 +-
 sysdeps/unix/sysv/linux/Versions              |   4 +
 sysdeps/unix/sysv/linux/aarch64/bits/rseq.h   |  24 ++
 sysdeps/unix/sysv/linux/aarch64/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist    |   2 +
 sysdeps/unix/sysv/linux/arm/bits/rseq.h       |  24 ++
 sysdeps/unix/sysv/linux/arm/libc.abilist      |   2 +
 sysdeps/unix/sysv/linux/bits/rseq.h           |  24 ++
 sysdeps/unix/sysv/linux/hppa/libc.abilist     |   2 +
 sysdeps/unix/sysv/linux/i386/libc.abilist     |   2 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist     |   2 +
 .../sysv/linux/m68k/coldfire/libc.abilist     |   2 +
 .../unix/sysv/linux/m68k/m680x0/libc.abilist  |   2 +
 .../unix/sysv/linux/microblaze/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/mips/bits/rseq.h      |  24 ++
 .../sysv/linux/mips/mips32/fpu/libc.abilist   |   2 +
 .../sysv/linux/mips/mips32/nofpu/libc.abilist |   2 +
 .../sysv/linux/mips/mips64/n32/libc.abilist   |   2 +
 .../sysv/linux/mips/mips64/n64/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist    |   2 +
 sysdeps/unix/sysv/linux/powerpc/bits/rseq.h   |  24 ++
 .../linux/powerpc/powerpc32/fpu/libc.abilist  |   2 +
 .../powerpc/powerpc32/nofpu/libc.abilist      |   2 +
 .../linux/powerpc/powerpc64/be/libc.abilist   |   2 +
 .../linux/powerpc/powerpc64/le/libc.abilist   |   2 +
 .../unix/sysv/linux/riscv/rv64/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/rseq-internal.h       |  91 +++++
 sysdeps/unix/sysv/linux/rseq-sym.c            |  54 +++
 sysdeps/unix/sysv/linux/s390/bits/rseq.h      |  24 ++
 .../unix/sysv/linux/s390/s390-32/libc.abilist |   2 +
 .../unix/sysv/linux/s390/s390-64/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/sched_getcpu.c        |  25 +-
 sysdeps/unix/sysv/linux/sh/libc.abilist       |   2 +
 .../sysv/linux/sparc/sparc32/libc.abilist     |   2 +
 .../sysv/linux/sparc/sparc64/libc.abilist     |   2 +
 sysdeps/unix/sysv/linux/sys/rseq.h            |  65 +++
 sysdeps/unix/sysv/linux/tst-rseq-nptl.c       | 381 ++++++++++++++++++
 sysdeps/unix/sysv/linux/tst-rseq.c            | 110 +++++
 sysdeps/unix/sysv/linux/x86/bits/rseq.h       |  24 ++
 .../unix/sysv/linux/x86_64/64/libc.abilist    |   2 +
 .../unix/sysv/linux/x86_64/x32/libc.abilist   |   2 +
 48 files changed, 1034 insertions(+), 15 deletions(-)
 create mode 100644 misc/rseq-internal.h
 create mode 100644 sysdeps/unix/sysv/linux/aarch64/bits/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/arm/bits/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/bits/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/mips/bits/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/rseq-internal.h
 create mode 100644 sysdeps/unix/sysv/linux/rseq-sym.c
 create mode 100644 sysdeps/unix/sysv/linux/s390/bits/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/sys/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/tst-rseq-nptl.c
 create mode 100644 sysdeps/unix/sysv/linux/tst-rseq.c
 create mode 100644 sysdeps/unix/sysv/linux/x86/bits/rseq.h

Comments

Carlos O'Donell March 22, 2019, 5:34 p.m. UTC | #1
On 2/12/19 2:42 PM, Mathieu Desnoyers wrote:
> The only point that still appears to not reach concensus is whether it's
> acceptable to define the RSEQ_SIG code signature for each architecture.
> If I missed other points that failed to reach concensus, please let me
> know!

I have no objection to RSEQ_SIG being a signature that each architecture uses.

Can you summarize the previous discussions here?
Florian Weimer March 22, 2019, 5:39 p.m. UTC | #2
* Mathieu Desnoyers:

> The only point that still appears to not reach concensus is whether it's
> acceptable to define the RSEQ_SIG code signature for each architecture.
> If I missed other points that failed to reach concensus, please let me
> know!

I still think the registration mechanism is very problematic and
should be avoided.
Carlos O'Donell March 22, 2019, 5:47 p.m. UTC | #3
On 3/22/19 1:39 PM, Florian Weimer wrote:
> * Mathieu Desnoyers:
> 
>> The only point that still appears to not reach concensus is whether it's
>> acceptable to define the RSEQ_SIG code signature for each architecture.
>> If I missed other points that failed to reach concensus, please let me
>> know!
> 
> I still think the registration mechanism is very problematic and
> should be avoided.

The *entire* registration mechanism?
Florian Weimer March 22, 2019, 5:51 p.m. UTC | #4
* Carlos O'Donell:

> On 3/22/19 1:39 PM, Florian Weimer wrote:
>> * Mathieu Desnoyers:
>> 
>>> The only point that still appears to not reach concensus is whether it's
>>> acceptable to define the RSEQ_SIG code signature for each architecture.
>>> If I missed other points that failed to reach concensus, please let me
>>> know!
>> 
>> I still think the registration mechanism is very problematic and
>> should be avoided.
>
> The *entire* registration mechanism?

The reference-counting part.  It's going to be of limited use, for a
few years at most, and we'll have to carry it forward indefinitely.
I don't think it's worth the complexity.
Mathieu Desnoyers March 22, 2019, 5:55 p.m. UTC | #5
----- On Mar 22, 2019, at 1:34 PM, Carlos O'Donell codonell@redhat.com wrote:

> On 2/12/19 2:42 PM, Mathieu Desnoyers wrote:
>> The only point that still appears to not reach concensus is whether it's
>> acceptable to define the RSEQ_SIG code signature for each architecture.
>> If I missed other points that failed to reach concensus, please let me
>> know!
> 
> I have no objection to RSEQ_SIG being a signature that each architecture uses.
> 
> Can you summarize the previous discussions here?

The culprit is whether we provide an architecture-agnostic "generic" value
for RSEQ_SIG for architectures that do not define a specific RSEQ_SIG, or
leave RSEQ_SIG undefined for architectures that do not define it yet.

Considering that RSEQ_SIG ends up being a 32-bit value that maps to actual
architecture code compiled into applications and libraries, it's
understandable that it needs to be defined for each architecture specifically.
For instance, generating invalid instructions may have ill effects on tools like
objdump, and may also have impact on the CPU speculative execution efficiency
in some cases.

There has been ideas floating around about having a "generic" value for
RSEQ_SIG that would apply to all architectures that do not override it.
However, if we have this, it makes it impossible for those architectures
to ever define a different value if they ever choose so, because that value
ends up being an ABI that is built into applications and libraries including
the glibc rseq header. Changing that value would break applications.

So I favor _not_ defining any generic RSEQ_SIG, and adding per-architecture
RSEQ_SIG define gradually. Therefore, user-space can #ifdef on whether
RSEQ_SIG is defined or not after including the glibc rseq header.

Thanks,

Mathieu
Carlos O'Donell March 22, 2019, 6:04 p.m. UTC | #6
On 3/22/19 1:55 PM, Mathieu Desnoyers wrote:
> ----- On Mar 22, 2019, at 1:34 PM, Carlos O'Donell codonell@redhat.com wrote:
> 
>> On 2/12/19 2:42 PM, Mathieu Desnoyers wrote:
>>> The only point that still appears to not reach concensus is whether it's
>>> acceptable to define the RSEQ_SIG code signature for each architecture.
>>> If I missed other points that failed to reach concensus, please let me
>>> know!
>>
>> I have no objection to RSEQ_SIG being a signature that each architecture uses.
>>
>> Can you summarize the previous discussions here?
> 
> The culprit is whether we provide an architecture-agnostic "generic" value
> for RSEQ_SIG for architectures that do not define a specific RSEQ_SIG, or
> leave RSEQ_SIG undefined for architectures that do not define it yet.
> 
> Considering that RSEQ_SIG ends up being a 32-bit value that maps to actual
> architecture code compiled into applications and libraries, it's
> understandable that it needs to be defined for each architecture specifically.
> For instance, generating invalid instructions may have ill effects on tools like
> objdump, and may also have impact on the CPU speculative execution efficiency
> in some cases.
> 
> There has been ideas floating around about having a "generic" value for
> RSEQ_SIG that would apply to all architectures that do not override it.
> However, if we have this, it makes it impossible for those architectures
> to ever define a different value if they ever choose so, because that value
> ends up being an ABI that is built into applications and libraries including
> the glibc rseq header. Changing that value would break applications.
> 
> So I favor _not_ defining any generic RSEQ_SIG, and adding per-architecture
> RSEQ_SIG define gradually. Therefore, user-space can #ifdef on whether
> RSEQ_SIG is defined or not after including the glibc rseq header.

That makes perfect sense.

I was particularly worried about hardware that wasn't designed for
having constant pools and injecting invalid instructions into that
stream can worse speculative execution and break developer tools that
need to know about new instructions (like valgrind).
Carlos O'Donell March 22, 2019, 7:45 p.m. UTC | #7
On 3/22/19 1:51 PM, Florian Weimer wrote:
> * Carlos O'Donell:
> 
>> On 3/22/19 1:39 PM, Florian Weimer wrote:
>>> * Mathieu Desnoyers:
>>>
>>>> The only point that still appears to not reach concensus is whether it's
>>>> acceptable to define the RSEQ_SIG code signature for each architecture.
>>>> If I missed other points that failed to reach concensus, please let me
>>>> know!
>>>
>>> I still think the registration mechanism is very problematic and
>>> should be avoided.
>>
>> The *entire* registration mechanism?
> 
> The reference-counting part.  It's going to be of limited use, for a
> few years at most, and we'll have to carry it forward indefinitely.
> I don't think it's worth the complexity.

I can understand Mathieu's position here, he wants to enable all
kinds of users, and wants to write libraries that use rseq today
but which work with future glibc. This is a perfectly reasonable
thing to want. The question we have to ask is the cost.

My suggestion is as follows, tell me what you think:

(a) Add a RSEQ_REGISTER_ALWAYS. The meaning of which is that the
     core C library does unconditional registration/unregistration
     for all threads, and that your application must not call
     rseq with flags 0 (register)/RSEQ_FLAG_UNREGISTER.

(b) In a few years we remove all the ref count code and define
     a __rseq_lib_abi with a register_state that is set to
     a constant value of RSEQ_REGISTER_ALWAYS, and do nothing else.

This way we have a way to backout the ref count process and just
leave a public data symbol as the only part of the ABI.

My idea is that we just need one more RSEQ_REGISTER_* value to
indicate that libc has taken over unconditional registration.

Thoughts?
Mathieu Desnoyers March 22, 2019, 8:14 p.m. UTC | #8
----- On Mar 22, 2019, at 3:45 PM, Carlos O'Donell codonell@redhat.com wrote:

> On 3/22/19 1:51 PM, Florian Weimer wrote:
>> * Carlos O'Donell:
>> 
>>> On 3/22/19 1:39 PM, Florian Weimer wrote:
>>>> * Mathieu Desnoyers:
>>>>
>>>>> The only point that still appears to not reach concensus is whether it's
>>>>> acceptable to define the RSEQ_SIG code signature for each architecture.
>>>>> If I missed other points that failed to reach concensus, please let me
>>>>> know!
>>>>
>>>> I still think the registration mechanism is very problematic and
>>>> should be avoided.
>>>
>>> The *entire* registration mechanism?
>> 
>> The reference-counting part.  It's going to be of limited use, for a
>> few years at most, and we'll have to carry it forward indefinitely.
>> I don't think it's worth the complexity.
> 
> I can understand Mathieu's position here, he wants to enable all
> kinds of users, and wants to write libraries that use rseq today
> but which work with future glibc. This is a perfectly reasonable
> thing to want. The question we have to ask is the cost.
> 
> My suggestion is as follows, tell me what you think:
> 
> (a) Add a RSEQ_REGISTER_ALWAYS. The meaning of which is that the
>     core C library does unconditional registration/unregistration
>     for all threads, and that your application must not call
>     rseq with flags 0 (register)/RSEQ_FLAG_UNREGISTER.
> 
> (b) In a few years we remove all the ref count code and define
>     a __rseq_lib_abi with a register_state that is set to
>     a constant value of RSEQ_REGISTER_ALWAYS, and do nothing else.
> 
> This way we have a way to backout the ref count process and just
> leave a public data symbol as the only part of the ABI.
> 
> My idea is that we just need one more RSEQ_REGISTER_* value to
> indicate that libc has taken over unconditional registration.
> 
> Thoughts?

I think we can do even simpler.

We can move the TLS refcount and state to an external library (librseq).

glibc would expose a new global "int" variable symbol __rseq_handled acting as
a boolean. It would be initially 0. glibc would set it to 1 in its C startup
code when it effectively handles rseq registration. That symbol would _not_ be
a TLS (it's global).

librseq would be a new library used by early rseq adopters. It would expose a
rseq register/unregister API, which internally would:

- Check whether __rseq_handled is true. If so, it would do nothing, leaving
  rseq registration to the libc.
- If __rseq_handled is false, deal with many early adopters with TLS refcount
  and state variables internal to librseq.so.

That should take care of minimizing those metrics:
- glibc ABI complexity and maintenance burden in the long term,
- pain for rseq early adopters when upgrading to newer glibc,

Does that make sense ?

Thanks,

Mathieu