2023-05-31 09:29:45 |
Simon Chopin |
description |
I'm working with Xen and libxenstore. libxenstore, when using a "watch", spawns a pthread (read_thread). When libxenstore shuts down, it pthread_cancel()s and pthread_join()s the "watch" thread.
That thread never exits and the process shutdown hangs.
read_threads is sitting in __read_chk(). In glibc 2.35, __read_chk is not a cancellation point, so the thread never reacts to the cancellation.
Upstream glibc fixed it in 2.36 in https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=dc30acf20bd635d71cd4c84100e842fdf0429e48
Here's the 2.35 disassembly - the lack of __pthread_enable_asynccancel() indicates the missing cancellation support:
(gdb) disassemble
Dump of assembler code for function __read_chk:
0x00007ffff7ea04d0 <+0>: endbr64
0x00007ffff7ea04d4 <+4>: cmp %rcx,%rdx
0x00007ffff7ea04d7 <+7>: ja 0x7ffff7ea0504 <__read_chk+52>
0x00007ffff7ea04d9 <+9>: xor %eax,%eax
0x00007ffff7ea04db <+11>: syscall
=> 0x00007ffff7ea04dd <+13>: cmp $0xfffffffffffff000,%rax
0x00007ffff7ea04e3 <+19>: ja 0x7ffff7ea04f0 <__read_chk+32>
0x00007ffff7ea04e5 <+21>: ret
0x00007ffff7ea04e6 <+22>: cs nopw 0x0(%rax,%rax,1)
0x00007ffff7ea04f0 <+32>: mov 0xe3919(%rip),%rdx # 0x7ffff7f83e10
0x00007ffff7ea04f7 <+39>: neg %eax
0x00007ffff7ea04f9 <+41>: mov %eax,%fs:(%rdx)
0x00007ffff7ea04fc <+44>: mov $0xffffffffffffffff,%rax
0x00007ffff7ea0503 <+51>: ret
0x00007ffff7ea0504 <+52>: push %rax
0x00007ffff7ea0505 <+53>: call 0x7ffff7ea00b0 <__GI___chk_fail>
End of assembler dump.
ProblemType: Bug
DistroRelease: Ubuntu 22.04
Package: libc6 2.35-0ubuntu3.1
ProcVersionSignature: Ubuntu 5.15.0-60.66-generic 5.15.78
Uname: Linux 5.15.0-60-generic x86_64
ApportVersion: 2.20.11-0ubuntu82.3
Architecture: amd64
CasperMD5CheckResult: unknown
CurrentDesktop: XFCE
Date: Sun Feb 19 21:03:32 2023
EcryptfsInUse: Yes
InstallationDate: Installed on 2012-12-06 (3727 days ago)
InstallationMedia: Ubuntu 12.10 "Quantal Quetzal" - Release amd64 (20121017.5)
SourcePackage: glibc
UpgradeStatus: Upgraded to jammy on 2022-07-24 (210 days ago) |
[Impact]
I'm working with Xen and libxenstore. libxenstore, when using a "watch", spawns a pthread (read_thread). When libxenstore shuts down, it pthread_cancel()s and pthread_join()s the "watch" thread.
That thread never exits and the process shutdown hangs.
read_threads is sitting in __read_chk(). In glibc 2.35, __read_chk is not a cancellation point, so the thread never reacts to the cancellation.
Upstream glibc fixed it in 2.36 in https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=dc30acf20bd635d71cd4c84100e842fdf0429e48
Here's the 2.35 disassembly - the lack of __pthread_enable_asynccancel() indicates the missing cancellation support:
(gdb) disassemble
Dump of assembler code for function __read_chk:
0x00007ffff7ea04d0 <+0>: endbr64
0x00007ffff7ea04d4 <+4>: cmp %rcx,%rdx
0x00007ffff7ea04d7 <+7>: ja 0x7ffff7ea0504 <__read_chk+52>
0x00007ffff7ea04d9 <+9>: xor %eax,%eax
0x00007ffff7ea04db <+11>: syscall
=> 0x00007ffff7ea04dd <+13>: cmp $0xfffffffffffff000,%rax
0x00007ffff7ea04e3 <+19>: ja 0x7ffff7ea04f0 <__read_chk+32>
0x00007ffff7ea04e5 <+21>: ret
0x00007ffff7ea04e6 <+22>: cs nopw 0x0(%rax,%rax,1)
0x00007ffff7ea04f0 <+32>: mov 0xe3919(%rip),%rdx # 0x7ffff7f83e10
0x00007ffff7ea04f7 <+39>: neg %eax
0x00007ffff7ea04f9 <+41>: mov %eax,%fs:(%rdx)
0x00007ffff7ea04fc <+44>: mov $0xffffffffffffffff,%rax
0x00007ffff7ea0503 <+51>: ret
0x00007ffff7ea0504 <+52>: push %rax
0x00007ffff7ea0505 <+53>: call 0x7ffff7ea00b0 <__GI___chk_fail>
End of assembler dump.
[Test procedure]
The patch includes a test for this that is run at build time.
[Regression potential]
Besides the usual risks with any glibc update, this could potentially surface some race conditions at thread shutdown in user applications that were thus far hidden by the lack of cancellation point. |
|