authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-01-17 06:02:54+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-04-22 15:31:56+02:00
log3df246905fbf96083014289bb6df8d997e9f563d
tree77ec11a03527c2b6ba6b4ece1dec651683cbb8aa
parent20f08ad09c515099b316e3624e0986cdcb8d2b93
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

libtsan: update to LLVM 22


74 files changed, 1910 insertions(+), 555 deletions(-)

lib/libtsan/LICENSE.TXT created+311
......@@ -0,0 +1,311 @@
1==============================================================================
2The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
3==============================================================================
4
5 Apache License
6 Version 2.0, January 2004
7 http://www.apache.org/licenses/
8
9 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
10
11 1. Definitions.
12
13 "License" shall mean the terms and conditions for use, reproduction,
14 and distribution as defined by Sections 1 through 9 of this document.
15
16 "Licensor" shall mean the copyright owner or entity authorized by
17 the copyright owner that is granting the License.
18
19 "Legal Entity" shall mean the union of the acting entity and all
20 other entities that control, are controlled by, or are under common
21 control with that entity. For the purposes of this definition,
22 "control" means (i) the power, direct or indirect, to cause the
23 direction or management of such entity, whether by contract or
24 otherwise, or (ii) ownership of fifty percent (50%) or more of the
25 outstanding shares, or (iii) beneficial ownership of such entity.
26
27 "You" (or "Your") shall mean an individual or Legal Entity
28 exercising permissions granted by this License.
29
30 "Source" form shall mean the preferred form for making modifications,
31 including but not limited to software source code, documentation
32 source, and configuration files.
33
34 "Object" form shall mean any form resulting from mechanical
35 transformation or translation of a Source form, including but
36 not limited to compiled object code, generated documentation,
37 and conversions to other media types.
38
39 "Work" shall mean the work of authorship, whether in Source or
40 Object form, made available under the License, as indicated by a
41 copyright notice that is included in or attached to the work
42 (an example is provided in the Appendix below).
43
44 "Derivative Works" shall mean any work, whether in Source or Object
45 form, that is based on (or derived from) the Work and for which the
46 editorial revisions, annotations, elaborations, or other modifications
47 represent, as a whole, an original work of authorship. For the purposes
48 of this License, Derivative Works shall not include works that remain
49 separable from, or merely link (or bind by name) to the interfaces of,
50 the Work and Derivative Works thereof.
51
52 "Contribution" shall mean any work of authorship, including
53 the original version of the Work and any modifications or additions
54 to that Work or Derivative Works thereof, that is intentionally
55 submitted to Licensor for inclusion in the Work by the copyright owner
56 or by an individual or Legal Entity authorized to submit on behalf of
57 the copyright owner. For the purposes of this definition, "submitted"
58 means any form of electronic, verbal, or written communication sent
59 to the Licensor or its representatives, including but not limited to
60 communication on electronic mailing lists, source code control systems,
61 and issue tracking systems that are managed by, or on behalf of, the
62 Licensor for the purpose of discussing and improving the Work, but
63 excluding communication that is conspicuously marked or otherwise
64 designated in writing by the copyright owner as "Not a Contribution."
65
66 "Contributor" shall mean Licensor and any individual or Legal Entity
67 on behalf of whom a Contribution has been received by Licensor and
68 subsequently incorporated within the Work.
69
70 2. Grant of Copyright License. Subject to the terms and conditions of
71 this License, each Contributor hereby grants to You a perpetual,
72 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
73 copyright license to reproduce, prepare Derivative Works of,
74 publicly display, publicly perform, sublicense, and distribute the
75 Work and such Derivative Works in Source or Object form.
76
77 3. Grant of Patent License. Subject to the terms and conditions of
78 this License, each Contributor hereby grants to You a perpetual,
79 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
80 (except as stated in this section) patent license to make, have made,
81 use, offer to sell, sell, import, and otherwise transfer the Work,
82 where such license applies only to those patent claims licensable
83 by such Contributor that are necessarily infringed by their
84 Contribution(s) alone or by combination of their Contribution(s)
85 with the Work to which such Contribution(s) was submitted. If You
86 institute patent litigation against any entity (including a
87 cross-claim or counterclaim in a lawsuit) alleging that the Work
88 or a Contribution incorporated within the Work constitutes direct
89 or contributory patent infringement, then any patent licenses
90 granted to You under this License for that Work shall terminate
91 as of the date such litigation is filed.
92
93 4. Redistribution. You may reproduce and distribute copies of the
94 Work or Derivative Works thereof in any medium, with or without
95 modifications, and in Source or Object form, provided that You
96 meet the following conditions:
97
98 (a) You must give any other recipients of the Work or
99 Derivative Works a copy of this License; and
100
101 (b) You must cause any modified files to carry prominent notices
102 stating that You changed the files; and
103
104 (c) You must retain, in the Source form of any Derivative Works
105 that You distribute, all copyright, patent, trademark, and
106 attribution notices from the Source form of the Work,
107 excluding those notices that do not pertain to any part of
108 the Derivative Works; and
109
110 (d) If the Work includes a "NOTICE" text file as part of its
111 distribution, then any Derivative Works that You distribute must
112 include a readable copy of the attribution notices contained
113 within such NOTICE file, excluding those notices that do not
114 pertain to any part of the Derivative Works, in at least one
115 of the following places: within a NOTICE text file distributed
116 as part of the Derivative Works; within the Source form or
117 documentation, if provided along with the Derivative Works; or,
118 within a display generated by the Derivative Works, if and
119 wherever such third-party notices normally appear. The contents
120 of the NOTICE file are for informational purposes only and
121 do not modify the License. You may add Your own attribution
122 notices within Derivative Works that You distribute, alongside
123 or as an addendum to the NOTICE text from the Work, provided
124 that such additional attribution notices cannot be construed
125 as modifying the License.
126
127 You may add Your own copyright statement to Your modifications and
128 may provide additional or different license terms and conditions
129 for use, reproduction, or distribution of Your modifications, or
130 for any such Derivative Works as a whole, provided Your use,
131 reproduction, and distribution of the Work otherwise complies with
132 the conditions stated in this License.
133
134 5. Submission of Contributions. Unless You explicitly state otherwise,
135 any Contribution intentionally submitted for inclusion in the Work
136 by You to the Licensor shall be under the terms and conditions of
137 this License, without any additional terms or conditions.
138 Notwithstanding the above, nothing herein shall supersede or modify
139 the terms of any separate license agreement you may have executed
140 with Licensor regarding such Contributions.
141
142 6. Trademarks. This License does not grant permission to use the trade
143 names, trademarks, service marks, or product names of the Licensor,
144 except as required for reasonable and customary use in describing the
145 origin of the Work and reproducing the content of the NOTICE file.
146
147 7. Disclaimer of Warranty. Unless required by applicable law or
148 agreed to in writing, Licensor provides the Work (and each
149 Contributor provides its Contributions) on an "AS IS" BASIS,
150 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
151 implied, including, without limitation, any warranties or conditions
152 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
153 PARTICULAR PURPOSE. You are solely responsible for determining the
154 appropriateness of using or redistributing the Work and assume any
155 risks associated with Your exercise of permissions under this License.
156
157 8. Limitation of Liability. In no event and under no legal theory,
158 whether in tort (including negligence), contract, or otherwise,
159 unless required by applicable law (such as deliberate and grossly
160 negligent acts) or agreed to in writing, shall any Contributor be
161 liable to You for damages, including any direct, indirect, special,
162 incidental, or consequential damages of any character arising as a
163 result of this License or out of the use or inability to use the
164 Work (including but not limited to damages for loss of goodwill,
165 work stoppage, computer failure or malfunction, or any and all
166 other commercial damages or losses), even if such Contributor
167 has been advised of the possibility of such damages.
168
169 9. Accepting Warranty or Additional Liability. While redistributing
170 the Work or Derivative Works thereof, You may choose to offer,
171 and charge a fee for, acceptance of support, warranty, indemnity,
172 or other liability obligations and/or rights consistent with this
173 License. However, in accepting such obligations, You may act only
174 on Your own behalf and on Your sole responsibility, not on behalf
175 of any other Contributor, and only if You agree to indemnify,
176 defend, and hold each Contributor harmless for any liability
177 incurred by, or claims asserted against, such Contributor by reason
178 of your accepting any such warranty or additional liability.
179
180 END OF TERMS AND CONDITIONS
181
182 APPENDIX: How to apply the Apache License to your work.
183
184 To apply the Apache License to your work, attach the following
185 boilerplate notice, with the fields enclosed by brackets "[]"
186 replaced with your own identifying information. (Don't include
187 the brackets!) The text should be enclosed in the appropriate
188 comment syntax for the file format. We also recommend that a
189 file or class name and description of purpose be included on the
190 same "printed page" as the copyright notice for easier
191 identification within third-party archives.
192
193 Copyright [yyyy] [name of copyright owner]
194
195 Licensed under the Apache License, Version 2.0 (the "License");
196 you may not use this file except in compliance with the License.
197 You may obtain a copy of the License at
198
199 http://www.apache.org/licenses/LICENSE-2.0
200
201 Unless required by applicable law or agreed to in writing, software
202 distributed under the License is distributed on an "AS IS" BASIS,
203 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
204 See the License for the specific language governing permissions and
205 limitations under the License.
206
207
208---- LLVM Exceptions to the Apache 2.0 License ----
209
210As an exception, if, as a result of your compiling your source code, portions
211of this Software are embedded into an Object form of such source code, you
212may redistribute such embedded portions in such Object form without complying
213with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
214
215In addition, if you combine or link compiled forms of this Software with
216software that is licensed under the GPLv2 ("Combined Software") and if a
217court of competent jurisdiction determines that the patent provision (Section
2183), the indemnity provision (Section 9) or other Section of the License
219conflicts with the conditions of the GPLv2, you may retroactively and
220prospectively choose to deem waived or otherwise exclude such Section(s) of
221the License, but only in their entirety and only with respect to the Combined
222Software.
223
224==============================================================================
225Software from third parties included in the LLVM Project:
226==============================================================================
227The LLVM Project contains third party software which is under different license
228terms. All such code will be identified clearly using at least one of two
229mechanisms:
2301) It will be in a separate directory tree with its own `LICENSE.txt` or
231 `LICENSE` file at the top containing the specific license and restrictions
232 which apply to that software, or
2332) It will contain specific license and restriction terms at the top of every
234 file.
235
236==============================================================================
237Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
238==============================================================================
239
240The compiler_rt library is dual licensed under both the University of Illinois
241"BSD-Like" license and the MIT license. As a user of this code you may choose
242to use it under either license. As a contributor, you agree to allow your code
243to be used under both.
244
245Full text of the relevant licenses is included below.
246
247==============================================================================
248
249University of Illinois/NCSA
250Open Source License
251
252Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
253
254All rights reserved.
255
256Developed by:
257
258 LLVM Team
259
260 University of Illinois at Urbana-Champaign
261
262 http://llvm.org
263
264Permission is hereby granted, free of charge, to any person obtaining a copy of
265this software and associated documentation files (the "Software"), to deal with
266the Software without restriction, including without limitation the rights to
267use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
268of the Software, and to permit persons to whom the Software is furnished to do
269so, subject to the following conditions:
270
271 * Redistributions of source code must retain the above copyright notice,
272 this list of conditions and the following disclaimers.
273
274 * Redistributions in binary form must reproduce the above copyright notice,
275 this list of conditions and the following disclaimers in the
276 documentation and/or other materials provided with the distribution.
277
278 * Neither the names of the LLVM Team, University of Illinois at
279 Urbana-Champaign, nor the names of its contributors may be used to
280 endorse or promote products derived from this Software without specific
281 prior written permission.
282
283THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
284IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
285FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
286CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
287LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
288OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
289SOFTWARE.
290
291==============================================================================
292
293Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
294
295Permission is hereby granted, free of charge, to any person obtaining a copy
296of this software and associated documentation files (the "Software"), to deal
297in the Software without restriction, including without limitation the rights
298to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
299copies of the Software, and to permit persons to whom the Software is
300furnished to do so, subject to the following conditions:
301
302The above copyright notice and this permission notice shall be included in
303all copies or substantial portions of the Software.
304
305THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
306IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
307FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
308AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
309LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
310OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
311THE SOFTWARE.
lib/libtsan/builtins/assembly.h+41-8
......@@ -14,7 +14,7 @@
1414#ifndef COMPILERRT_ASSEMBLY_H
1515#define COMPILERRT_ASSEMBLY_H
1616
17#if defined(__linux__) && defined(__CET__)
17#ifdef __CET__
1818#if __has_include(<cet.h>)
1919#include <cet.h>
2020#endif
......@@ -71,19 +71,35 @@
7171
7272#endif
7373
74#if defined(__aarch64__) && defined(__ELF__) && \
75 defined(COMPILER_RT_EXECUTE_ONLY_CODE)
76// The assembler always creates an implicit '.text' section with default flags
77// (SHF_ALLOC | SHF_EXECINSTR), which is incompatible with the execute-only
78// '.text' section we want to create here because of the missing
79// SHF_AARCH64_PURECODE section flag. To solve this, we use 'unique,0' to
80// differentiate the two sections. The output will therefore have two separate
81// sections named '.text', where code will be placed into the execute-only
82// '.text' section, and the implicitly-created one will be empty.
83#define TEXT_SECTION \
84 .section .text,"axy",@progbits,unique,0
85#else
86#define TEXT_SECTION \
87 .text
88#endif
89
7490#if defined(__arm__) || defined(__aarch64__) || defined(__arm64ec__)
7591#define FUNC_ALIGN \
76 .text SEPARATOR \
7792 .balign 16 SEPARATOR
7893#else
7994#define FUNC_ALIGN
8095#endif
8196
82// BTI and PAC gnu property note
97// BTI, PAC, and GCS gnu property note
8398#define NT_GNU_PROPERTY_TYPE_0 5
8499#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
85100#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI 1
86101#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC 2
102#define GNU_PROPERTY_AARCH64_FEATURE_1_GCS 4
87103
88104#if defined(__ARM_FEATURE_BTI_DEFAULT)
89105#define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI
......@@ -97,6 +113,12 @@
97113#define PAC_FLAG 0
98114#endif
99115
116#if defined(__ARM_FEATURE_GCS_DEFAULT)
117#define GCS_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_GCS
118#else
119#define GCS_FLAG 0
120#endif
121
100122#define GNU_PROPERTY(type, value) \
101123 .pushsection .note.gnu.property, "a" SEPARATOR \
102124 .p2align 3 SEPARATOR \
......@@ -118,11 +140,12 @@
118140#define BTI_J
119141#endif
120142
121#if (BTI_FLAG | PAC_FLAG) != 0
122#define GNU_PROPERTY_BTI_PAC \
123 GNU_PROPERTY(GNU_PROPERTY_AARCH64_FEATURE_1_AND, BTI_FLAG | PAC_FLAG)
143#if (BTI_FLAG | PAC_FLAG | GCS_FLAG) != 0
144#define GNU_PROPERTY_BTI_PAC_GCS \
145 GNU_PROPERTY(GNU_PROPERTY_AARCH64_FEATURE_1_AND, \
146 BTI_FLAG | PAC_FLAG | GCS_FLAG)
124147#else
125#define GNU_PROPERTY_BTI_PAC
148#define GNU_PROPERTY_BTI_PAC_GCS
126149#endif
127150
128151#if defined(__clang__) || defined(__GCC_HAVE_DWARF2_CFI_ASM)
......@@ -247,6 +270,7 @@
247270#endif
248271
249272#define DEFINE_COMPILERRT_FUNCTION(name) \
273 TEXT_SECTION SEPARATOR \
250274 DEFINE_CODE_STATE \
251275 FILE_LEVEL_DIRECTIVE SEPARATOR \
252276 .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
......@@ -256,6 +280,7 @@
256280 FUNC_SYMBOL(SYMBOL_NAME(name)):
257281
258282#define DEFINE_COMPILERRT_THUMB_FUNCTION(name) \
283 TEXT_SECTION SEPARATOR \
259284 DEFINE_CODE_STATE \
260285 FILE_LEVEL_DIRECTIVE SEPARATOR \
261286 .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
......@@ -265,6 +290,7 @@
265290 FUNC_SYMBOL(SYMBOL_NAME(name)):
266291
267292#define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name) \
293 TEXT_SECTION SEPARATOR \
268294 DEFINE_CODE_STATE \
269295 FILE_LEVEL_DIRECTIVE SEPARATOR \
270296 .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
......@@ -274,6 +300,7 @@
274300 FUNC_SYMBOL(SYMBOL_NAME(name)):
275301
276302#define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name) \
303 TEXT_SECTION SEPARATOR \
277304 DEFINE_CODE_STATE \
278305 .globl FUNC_SYMBOL(name) SEPARATOR \
279306 SYMBOL_IS_FUNC(name) SEPARATOR \
......@@ -282,6 +309,7 @@
282309 FUNC_SYMBOL(name):
283310
284311#define DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(name) \
312 TEXT_SECTION SEPARATOR \
285313 DEFINE_CODE_STATE \
286314 FUNC_ALIGN \
287315 .globl FUNC_SYMBOL(name) SEPARATOR \
......@@ -296,7 +324,7 @@
296324 .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
297325 SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
298326 DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \
299 .set FUNC_SYMBOL(SYMBOL_NAME(name)), FUNC_SYMBOL(target) SEPARATOR
327 .set FUNC_SYMBOL(SYMBOL_NAME(name)), FUNC_SYMBOL(SYMBOL_NAME(target)) SEPARATOR
300328
301329#if defined(__ARM_EABI__)
302330#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) \
......@@ -329,4 +357,9 @@
329357#endif
330358#endif
331359
360#if defined(__ASSEMBLER__) && (defined(__i386__) || defined(__amd64__)) && \
361 !defined(__arm64ec__)
362.att_syntax
363#endif
364
332365#endif // COMPILERRT_ASSEMBLY_H
lib/libtsan/interception/interception_win.cpp+4
......@@ -646,6 +646,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
646646 case 0xC033: // 33 C0 : xor eax, eax
647647 case 0xC933: // 33 C9 : xor ecx, ecx
648648 case 0xD233: // 33 D2 : xor edx, edx
649 case 0xFF33: // 33 FF : xor edi, edi
649650 case 0x9066: // 66 90 : xchg %ax,%ax (Two-byte NOP)
650651 case 0xDB84: // 84 DB : test bl,bl
651652 case 0xC084: // 84 C0 : test al,al
......@@ -764,6 +765,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
764765
765766 switch (0x00FFFFFF & *(u32 *)address) {
766767 case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax]
768 case 0x02b70f: // 0f b7 02 : movzx eax, WORD PTR [rdx]
767769 case 0xc00b4d: // 4d 0b c0 : or r8, r8
768770 case 0xc03345: // 45 33 c0 : xor r8d, r8d
769771 case 0xc08548: // 48 85 c0 : test rax, rax
......@@ -799,6 +801,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
799801 case 0xc9854d: // 4d 85 c9 : test r9, r9
800802 case 0xc98b4c: // 4c 8b c9 : mov r9, rcx
801803 case 0xd12948: // 48 29 d1 : sub rcx, rdx
804 case 0xc22b4c: // 4c 2b c2 : sub r8, rdx
802805 case 0xca2b48: // 48 2b ca : sub rcx, rdx
803806 case 0xca3b48: // 48 3b ca : cmp rcx, rdx
804807 case 0xd12b48: // 48 2b d1 : sub rdx, rcx
......@@ -813,6 +816,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
813816 case 0xd9f748: // 48 f7 d9 : neg rcx
814817 case 0xc03145: // 45 31 c0 : xor r8d,r8d
815818 case 0xc93145: // 45 31 c9 : xor r9d,r9d
819 case 0xd23345: // 45 33 d2 : xor r10d, r10d
816820 case 0xdb3345: // 45 33 db : xor r11d, r11d
817821 case 0xc08445: // 45 84 c0 : test r8b,r8b
818822 case 0xd28445: // 45 84 d2 : test r10b,r10b
lib/libtsan/sanitizer_common/sanitizer_allocator_primary32.h+1
......@@ -288,6 +288,7 @@ class SizeClassAllocator32 {
288288 uptr ComputeRegionId(uptr mem) const {
289289 if (SANITIZER_SIGN_EXTENDED_ADDRESSES)
290290 mem &= (kSpaceSize - 1);
291 mem -= kSpaceBeg;
291292 const uptr res = mem >> kRegionSizeLog;
292293 CHECK_LT(res, kNumPossibleRegions);
293294 return res;
lib/libtsan/sanitizer_common/sanitizer_allocator_primary64.h+18
......@@ -113,6 +113,24 @@ class SizeClassAllocator64 {
113113 // ~(uptr)0.
114114 void Init(s32 release_to_os_interval_ms, uptr heap_start = 0) {
115115 uptr TotalSpaceSize = kSpaceSize + AdditionalSize();
116
117 uptr MaxAddr = GetMaxUserVirtualAddress();
118 // VReport does not call the sanitizer allocator.
119 VReport(3, "Max user virtual address: 0x%zx\n", MaxAddr);
120 VReport(3, "Total space size for primary allocator: 0x%zx\n",
121 TotalSpaceSize);
122 // TODO: revise the check if we ever configure sanitizers to deliberately
123 // map beyond the 2**48 barrier (note that Linux pretends the VMA is
124 // limited to 48-bit for backwards compatibility, but allows apps to
125 // explicitly specify an address beyond that).
126 if (heap_start + TotalSpaceSize >= MaxAddr) {
127 // We can't easily adjust the requested heap size, because kSpaceSize is
128 // const (for optimization) and used throughout the code.
129 VReport(0, "Error: heap size %zx exceeds max user virtual address %zx\n",
130 TotalSpaceSize, MaxAddr);
131 VReport(
132 0, "Try using a kernel that allows a larger virtual address space\n");
133 }
116134 PremappedHeap = heap_start != 0;
117135 if (PremappedHeap) {
118136 CHECK(!kUsingConstantSpaceBeg);
lib/libtsan/sanitizer_common/sanitizer_common.h+15-2
......@@ -78,8 +78,8 @@ uptr GetMmapGranularity();
7878uptr GetMaxVirtualAddress();
7979uptr GetMaxUserVirtualAddress();
8080// Threads
81tid_t GetTid();
82int TgKill(pid_t pid, tid_t tid, int sig);
81ThreadID GetTid();
82int TgKill(pid_t pid, ThreadID tid, int sig);
8383uptr GetThreadSelf();
8484void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
8585 uptr *stack_bottom);
......@@ -390,6 +390,9 @@ void ReportDeadlySignal(const SignalContext &sig, u32 tid,
390390void SetAlternateSignalStack();
391391void UnsetAlternateSignalStack();
392392
393bool IsSignalHandlerFromSanitizer(int signum);
394bool SetSignalHandlerFromSanitizer(int signum, bool new_state);
395
393396// Construct a one-line string:
394397// SUMMARY: SanitizerToolName: error_message
395398// and pass it to __sanitizer_report_error_summary.
......@@ -484,6 +487,13 @@ inline uptr Log2(uptr x) {
484487 return LeastSignificantSetBitIndex(x);
485488}
486489
490inline bool IntervalsAreSeparate(uptr start1, uptr end1, uptr start2,
491 uptr end2) {
492 CHECK_LE(start1, end1);
493 CHECK_LE(start2, end2);
494 return (end1 < start2) || (end2 < start1);
495}
496
487497// Don't use std::min, std::max or std::swap, to minimize dependency
488498// on libstdc++.
489499template <class T>
......@@ -734,6 +744,7 @@ enum ModuleArch {
734744 kModuleArchARMV7S,
735745 kModuleArchARMV7K,
736746 kModuleArchARM64,
747 kModuleArchARM64E,
737748 kModuleArchLoongArch64,
738749 kModuleArchRISCV64,
739750 kModuleArchHexagon
......@@ -807,6 +818,8 @@ inline const char *ModuleArchToString(ModuleArch arch) {
807818 return "armv7k";
808819 case kModuleArchARM64:
809820 return "arm64";
821 case kModuleArchARM64E:
822 return "arm64e";
810823 case kModuleArchLoongArch64:
811824 return "loongarch64";
812825 case kModuleArchRISCV64:
lib/libtsan/sanitizer_common/sanitizer_common_interceptors.inc+30-4
......@@ -1285,8 +1285,34 @@ INTERCEPTOR(int, puts, char *s) {
12851285#endif
12861286
12871287#if SANITIZER_INTERCEPT_PRCTL
1288INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
1289 unsigned long arg4, unsigned long arg5) {
1288
1289# if defined(__aarch64__)
1290// https://llvm.org/docs/PointerAuth.html
1291// AArch64 is currently the only architecture with full PAC support.
1292// Avoid adding PAC instructions to prevent crashes caused by
1293// prctl(PR_PAC_RESET_KEYS, ...). Since PR_PAC_RESET_KEYS resets the
1294// authentication key, using the old key afterward will lead to a crash.
1295
1296# if defined(__ARM_FEATURE_BTI_DEFAULT)
1297# define BRANCH_PROTECTION_ATTRIBUTE \
1298 __attribute__((target("branch-protection=bti")))
1299# else
1300# define BRANCH_PROTECTION_ATTRIBUTE \
1301 __attribute__((target("branch-protection=none")))
1302# endif
1303
1304# define PRCTL_INTERCEPTOR(ret_type, func, ...) \
1305 DEFINE_REAL(ret_type, func, __VA_ARGS__) \
1306 DECLARE_WRAPPER(ret_type, func, __VA_ARGS__) \
1307 extern "C" INTERCEPTOR_ATTRIBUTE BRANCH_PROTECTION_ATTRIBUTE ret_type \
1308 WRAP(func)(__VA_ARGS__)
1309
1310# else
1311# define PRCTL_INTERCEPTOR INTERCEPTOR
1312# endif
1313
1314PRCTL_INTERCEPTOR(int, prctl, int option, unsigned long arg2,
1315 unsigned long arg3, unsigned long arg4, unsigned long arg5) {
12901316 void *ctx;
12911317 COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
12921318 static const int PR_SET_NAME = 15;
......@@ -1300,7 +1326,7 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
13001326 static const int PR_SET_SECCOMP = 22;
13011327 static const int SECCOMP_MODE_FILTER = 2;
13021328# endif
1303 if (option == PR_SET_VMA && arg2 == 0UL) {
1329 if (option == PR_SET_VMA && arg2 == 0UL && arg5 != 0UL) {
13041330 char *name = (char *)arg5;
13051331 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
13061332 }
......@@ -1326,7 +1352,7 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
13261352 }
13271353 return res;
13281354}
1329#define INIT_PRCTL COMMON_INTERCEPT_FUNCTION(prctl)
1355# define INIT_PRCTL COMMON_INTERCEPT_FUNCTION(prctl)
13301356#else
13311357#define INIT_PRCTL
13321358#endif // SANITIZER_INTERCEPT_PRCTL
lib/libtsan/sanitizer_common/sanitizer_common_interceptors_ioctl.inc+4
......@@ -344,12 +344,16 @@ static void ioctl_table_fill() {
344344 _(SOUND_PCM_WRITE_CHANNELS, WRITE, sizeof(int));
345345 _(SOUND_PCM_WRITE_FILTER, WRITE, sizeof(int));
346346 _(TCFLSH, NONE, 0);
347# if SANITIZER_TERMIOS_IOCTL_CONSTANTS
347348 _(TCGETS, WRITE, struct_termios_sz);
349# endif
348350 _(TCSBRK, NONE, 0);
349351 _(TCSBRKP, NONE, 0);
352# if SANITIZER_TERMIOS_IOCTL_CONSTANTS
350353 _(TCSETS, READ, struct_termios_sz);
351354 _(TCSETSF, READ, struct_termios_sz);
352355 _(TCSETSW, READ, struct_termios_sz);
356# endif
353357 _(TCXONC, NONE, 0);
354358 _(TIOCGLCKTRMIOS, WRITE, struct_termios_sz);
355359 _(TIOCGSOFTCAR, WRITE, sizeof(int));
lib/libtsan/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S+2-1
......@@ -5,6 +5,7 @@
55
66ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA)
77
8TEXT_SECTION
89.comm _ZN14__interception10real_vforkE,8,8
910.globl ASM_WRAPPER_NAME(vfork)
1011ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
......@@ -43,6 +44,6 @@ ASM_SIZE(vfork)
4344ASM_INTERCEPTOR_TRAMPOLINE(vfork)
4445ASM_TRAMPOLINE_ALIAS(vfork, vfork)
4546
46GNU_PROPERTY_BTI_PAC
47GNU_PROPERTY_BTI_PAC_GCS
4748
4849#endif
lib/libtsan/sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S+2
......@@ -2,6 +2,8 @@
22
33#include "sanitizer_common/sanitizer_asm.h"
44
5.att_syntax
6
57.comm _ZN14__interception10real_vforkE,4,4
68.globl ASM_WRAPPER_NAME(vfork)
79ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
lib/libtsan/sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S+2
......@@ -2,6 +2,8 @@
22
33#include "sanitizer_common/sanitizer_asm.h"
44
5.att_syntax
6
57.comm _ZN14__interception10real_vforkE,8,8
68.globl ASM_WRAPPER_NAME(vfork)
79ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
lib/libtsan/sanitizer_common/sanitizer_common_syscalls.inc+18
......@@ -143,6 +143,12 @@ struct sanitizer_kernel_sockaddr {
143143 char sa_data[14];
144144};
145145
146struct sanitizer_kernel_open_how {
147 u64 flags;
148 u64 mode;
149 u64 resolve;
150};
151
146152// Real sigset size is always passed as a syscall argument.
147153// Declare it "void" to catch sizeof(kernel_sigset_t).
148154typedef void kernel_sigset_t;
......@@ -2843,6 +2849,18 @@ PRE_SYSCALL(openat)(long dfd, const void *filename, long flags, long mode) {
28432849POST_SYSCALL(openat)
28442850(long res, long dfd, const void *filename, long flags, long mode) {}
28452851
2852PRE_SYSCALL(openat2)(long dfd, const void* filename,
2853 const sanitizer_kernel_open_how* how, uptr howlen) {
2854 if (filename)
2855 PRE_READ(filename, __sanitizer::internal_strlen((const char*)filename) + 1);
2856
2857 if (how)
2858 PRE_READ(how, howlen);
2859}
2860
2861POST_SYSCALL(openat2)(long res, long dfd, const void* filename,
2862 const sanitizer_kernel_open_how* how, uptr howlen) {}
2863
28462864PRE_SYSCALL(newfstatat)
28472865(long dfd, const void *filename, void *statbuf, long flag) {
28482866 if (filename)
lib/libtsan/sanitizer_common/sanitizer_coverage_interface.inc deleted-43
......@@ -1,43 +0,0 @@
1//===-- sanitizer_coverage_interface.inc ----------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8// Sanitizer Coverage interface list.
9//===----------------------------------------------------------------------===//
10INTERFACE_FUNCTION(__sanitizer_cov_dump)
11INTERFACE_FUNCTION(__sanitizer_cov_reset)
12INTERFACE_FUNCTION(__sanitizer_dump_coverage)
13INTERFACE_FUNCTION(__sanitizer_dump_trace_pc_guard_coverage)
14INTERFACE_WEAK_FUNCTION(__sancov_default_options)
15INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp)
16INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp1)
17INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp2)
18INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp4)
19INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp8)
20INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp1)
21INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp2)
22INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp4)
23INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp8)
24INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_div4)
25INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_div8)
26INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_gep)
27INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_guard)
28INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_guard_init)
29INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_indir)
30INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load1)
31INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load2)
32INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load4)
33INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load8)
34INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load16)
35INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store1)
36INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store2)
37INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store4)
38INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store8)
39INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store16)
40INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_switch)
41INTERFACE_WEAK_FUNCTION(__sanitizer_cov_8bit_counters_init)
42INTERFACE_WEAK_FUNCTION(__sanitizer_cov_bool_flag_init)
43INTERFACE_WEAK_FUNCTION(__sanitizer_cov_pcs_init)
lib/libtsan/sanitizer_common/sanitizer_file.cpp+40-12
......@@ -36,9 +36,17 @@ void RawWrite(const char *buffer) {
3636
3737void ReportFile::ReopenIfNecessary() {
3838 mu->CheckLocked();
39 if (fd == kStdoutFd || fd == kStderrFd) return;
40
4139 uptr pid = internal_getpid();
40 if (fallbackToStderrActive && fd_pid != pid) {
41 // If fallbackToStderrActive is set then we fellback to stderr. If this is a
42 // new process, mark fd as invalid so we attempt to open again.
43 CHECK_EQ(fd, kStderrFd);
44 fd = kInvalidFd;
45 fallbackToStderrActive = false;
46 }
47 if (fd == kStdoutFd || fd == kStderrFd)
48 return;
49
4250 // If in tracer, use the parent's file.
4351 if (pid == stoptheworld_tracer_pid)
4452 pid = stoptheworld_tracer_ppid;
......@@ -48,8 +56,7 @@ void ReportFile::ReopenIfNecessary() {
4856 // process, close it now.
4957 if (fd_pid == pid)
5058 return;
51 else
52 CloseFile(fd);
59 CloseFile(fd);
5360 }
5461
5562 const char *exe_name = GetProcessName();
......@@ -65,18 +72,24 @@ void ReportFile::ReopenIfNecessary() {
6572 error_t err;
6673 fd = OpenFile(full_path, WrOnly, &err);
6774 if (fd == kInvalidFd) {
68 const char *ErrorMsgPrefix = "ERROR: Can't open file: ";
75 bool fallback = common_flags()->log_fallback_to_stderr;
76 const char *ErrorMsgPrefix =
77 fallback ? "WARNING: Can't open file, falling back to stderr: "
78 : "ERROR: Can't open file: ";
6979 WriteToFile(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix));
7080 WriteToFile(kStderrFd, full_path, internal_strlen(full_path));
7181 char errmsg[100];
7282 internal_snprintf(errmsg, sizeof(errmsg), " (reason: %d)\n", err);
7383 WriteToFile(kStderrFd, errmsg, internal_strlen(errmsg));
74 Die();
84 if (!fallback)
85 Die();
86 fallbackToStderrActive = true;
87 fd = kStderrFd;
7588 }
7689 fd_pid = pid;
7790}
7891
79static void RecursiveCreateParentDirs(char *path) {
92static void RecursiveCreateParentDirs(char *path, fd_t &fd) {
8093 if (path[0] == '\0')
8194 return;
8295 for (int i = 1; path[i] != '\0'; ++i) {
......@@ -85,12 +98,19 @@ static void RecursiveCreateParentDirs(char *path) {
8598 continue;
8699 path[i] = '\0';
87100 if (!DirExists(path) && !CreateDir(path)) {
88 const char *ErrorMsgPrefix = "ERROR: Can't create directory: ";
101 bool fallback = common_flags()->log_fallback_to_stderr;
102 const char *ErrorMsgPrefix =
103 fallback ? "WARNING: Can't create directory, falling back to stderr: "
104 : "ERROR: Can't create directory: ";
89105 WriteToFile(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix));
90106 WriteToFile(kStderrFd, path, internal_strlen(path));
91107 const char *ErrorMsgSuffix = "\n";
92108 WriteToFile(kStderrFd, ErrorMsgSuffix, internal_strlen(ErrorMsgSuffix));
93 Die();
109 if (!fallback)
110 Die();
111 path[i] = save;
112 fd = kStderrFd;
113 return;
94114 }
95115 path[i] = save;
96116 }
......@@ -108,6 +128,9 @@ static void ParseAndSetPath(const char *pattern, char *dest,
108128 CHECK(dest);
109129 CHECK_GE(dest_size, 1);
110130 dest[0] = '\0';
131 // Return empty string if empty string was passed
132 if (internal_strlen(pattern) == 0)
133 return;
111134 uptr next_substr_start_idx = 0;
112135 for (uptr i = 0; i < internal_strlen(pattern) - 1; i++) {
113136 if (pattern[i] != '%')
......@@ -161,12 +184,17 @@ void ReportFile::SetReportPath(const char *path) {
161184 if (path) {
162185 uptr len = internal_strlen(path);
163186 if (len > sizeof(path_prefix) - 100) {
164 const char *message = "ERROR: Path is too long: ";
187 bool fallback = common_flags()->log_fallback_to_stderr;
188 const char *message =
189 fallback ? "WARNING: Path is too long, falling back to stderr: "
190 : "ERROR: Path is too long: ";
165191 WriteToFile(kStderrFd, message, internal_strlen(message));
166192 WriteToFile(kStderrFd, path, 8);
167193 message = "...\n";
168194 WriteToFile(kStderrFd, message, internal_strlen(message));
169 Die();
195 if (!fallback)
196 Die();
197 path = "stderr";
170198 }
171199 }
172200
......@@ -180,7 +208,7 @@ void ReportFile::SetReportPath(const char *path) {
180208 fd = kStdoutFd;
181209 } else {
182210 ParseAndSetPath(path, path_prefix, kMaxPathLength);
183 RecursiveCreateParentDirs(path_prefix);
211 RecursiveCreateParentDirs(path_prefix, fd);
184212 }
185213}
186214
lib/libtsan/sanitizer_common/sanitizer_file.h+3
......@@ -43,6 +43,9 @@ struct ReportFile {
4343 // PID of the process that opened fd. If a fork() occurs,
4444 // the PID of child will be different from fd_pid.
4545 uptr fd_pid;
46 // Set to true if the last attempt to open the logfile failed, perhaps due to
47 // permission errors
48 bool fallbackToStderrActive = false;
4649
4750 private:
4851 void ReopenIfNecessary();
lib/libtsan/sanitizer_common/sanitizer_flags.inc+7
......@@ -65,6 +65,8 @@ COMMON_FLAG(
6565 bool, log_to_syslog, (bool)SANITIZER_ANDROID || (bool)SANITIZER_APPLE,
6666 "Write all sanitizer output to syslog in addition to other means of "
6767 "logging.")
68COMMON_FLAG(bool, log_fallback_to_stderr, false,
69 "When set, fallback to stderr if we are unable to open log path.")
6870COMMON_FLAG(
6971 int, verbosity, 0,
7072 "Verbosity level (0 - silent, 1 - a bit of output, 2+ - more output).")
......@@ -111,6 +113,11 @@ COMMON_FLAG(HandleSignalMode, handle_sigfpe, kHandleSignalYes,
111113COMMON_FLAG(bool, allow_user_segv_handler, true,
112114 "Deprecated. True has no effect, use handle_sigbus=1. If false, "
113115 "handle_*=1 will be upgraded to handle_*=2.")
116COMMON_FLAG(bool, cloak_sanitizer_signal_handlers, false,
117 "If set, signal/sigaction will pretend that sanitizers did not "
118 "preinstall any signal handlers. If the user subsequently installs "
119 "a signal handler, this will disable cloaking for the respective "
120 "signal.")
114121COMMON_FLAG(bool, use_sigaltstack, true,
115122 "If set, uses alternate stack for signal handling.")
116123COMMON_FLAG(bool, detect_deadlocks, true,
lib/libtsan/sanitizer_common/sanitizer_fuchsia.cpp+30-3
......@@ -14,6 +14,7 @@
1414#include "sanitizer_fuchsia.h"
1515#if SANITIZER_FUCHSIA
1616
17# include <limits.h>
1718# include <pthread.h>
1819# include <stdlib.h>
1920# include <unistd.h>
......@@ -68,7 +69,7 @@ int internal_dlinfo(void *handle, int request, void *p) { UNIMPLEMENTED(); }
6869
6970uptr GetThreadSelf() { return reinterpret_cast<uptr>(thrd_current()); }
7071
71tid_t GetTid() { return GetThreadSelf(); }
72ThreadID GetTid() { return GetThreadSelf(); }
7273
7374void Abort() { abort(); }
7475
......@@ -117,11 +118,37 @@ uptr GetMmapGranularity() { return _zx_system_get_page_size(); }
117118
118119sanitizer_shadow_bounds_t ShadowBounds;
119120
121// Any sanitizer that utilizes shadow should explicitly call whenever it's
122// appropriate for that sanitizer to reference shadow bounds. For ASan, this is
123// done in `InitializeShadowMemory` and for HWASan, this is done in
124// `InitShadow`.
120125void InitShadowBounds() { ShadowBounds = __sanitizer_shadow_bounds(); }
121126
127// TODO(leonardchan): It's not immediately clear from a user perspective if
128// `GetMaxUserVirtualAddress` should be called exatly once on runtime startup
129// or can be called multiple times. Currently it looks like most instances of
130// `GetMaxUserVirtualAddress` are meant to be called once, but if someone
131// decides to call this multiple times in the future, we should have a separate
132// function that's ok to call multiple times. Ideally we would just invoke this
133// syscall once. Also for Fuchsia, this syscall technically gets invoked twice
134// since `__sanitizer_shadow_bounds` also invokes this syscall under the hood.
122135uptr GetMaxUserVirtualAddress() {
123 InitShadowBounds();
124 return ShadowBounds.memory_limit - 1;
136 zx_info_vmar_t info;
137 zx_status_t status = _zx_object_get_info(_zx_vmar_root_self(), ZX_INFO_VMAR,
138 &info, sizeof(info), NULL, NULL);
139 CHECK_EQ(status, ZX_OK);
140
141 // Find the top of the accessible address space.
142 uintptr_t top = info.base + info.len;
143
144 // Round it up to a power-of-two size. There may be some pages at
145 // the top that can't actually be mapped, but for purposes of the
146 // the shadow, we'll pretend they could be.
147 int bit = (sizeof(uintptr_t) * CHAR_BIT) - __builtin_clzl(top);
148 if (top != (uintptr_t)1 << bit)
149 top = (uintptr_t)1 << (bit + 1);
150
151 return top - 1;
125152}
126153
127154uptr GetMaxVirtualAddress() { return GetMaxUserVirtualAddress(); }
lib/libtsan/sanitizer_common/sanitizer_haiku.cpp+2-2
......@@ -231,12 +231,12 @@ uptr internal_execve(const char *filename, char *const argv[],
231231}
232232
233233# if 0
234tid_t GetTid() {
234ThreadID GetTid() {
235235 DEFINE__REAL(int, _lwp_self);
236236 return _REAL(_lwp_self);
237237}
238238
239int TgKill(pid_t pid, tid_t tid, int sig) {
239int TgKill(pid_t pid, ThreadID tid, int sig) {
240240 DEFINE__REAL(int, _lwp_kill, int a, int b);
241241 (void)pid;
242242 return _REAL(_lwp_kill, tid, sig);
lib/libtsan/sanitizer_common/sanitizer_internal_defs.h+1-1
......@@ -209,7 +209,7 @@ typedef long ssize;
209209typedef sptr ssize;
210210#endif
211211
212typedef u64 tid_t;
212typedef u64 ThreadID;
213213
214214// ----------- ATTENTION -------------
215215// This header should NOT include any other headers to avoid portability issues.
lib/libtsan/sanitizer_common/sanitizer_libc.cpp+8
......@@ -190,6 +190,14 @@ uptr internal_strlcat(char *dst, const char *src, uptr maxlen) {
190190 return dstlen + srclen;
191191}
192192
193char* internal_strcat(char* dst, const char* src) {
194 uptr len = internal_strlen(dst);
195 uptr i;
196 for (i = 0; src[i]; i++) dst[len + i] = src[i];
197 dst[len + i] = 0;
198 return dst;
199}
200
193201char *internal_strncat(char *dst, const char *src, uptr n) {
194202 uptr len = internal_strlen(dst);
195203 uptr i;
lib/libtsan/sanitizer_common/sanitizer_libc.h+1
......@@ -59,6 +59,7 @@ char *internal_strdup(const char *s);
5959uptr internal_strlen(const char *s);
6060uptr internal_strlcat(char *dst, const char *src, uptr maxlen);
6161char *internal_strncat(char *dst, const char *src, uptr n);
62char* internal_strcat(char* dst, const char* src);
6263int internal_strncmp(const char *s1, const char *s2, uptr n);
6364uptr internal_strlcpy(char *dst, const char *src, uptr maxlen);
6465char *internal_strncpy(char *dst, const char *src, uptr n);
lib/libtsan/sanitizer_common/sanitizer_linux.cpp+15-7
......@@ -635,7 +635,7 @@ bool DirExists(const char *path) {
635635}
636636
637637# if !SANITIZER_NETBSD
638tid_t GetTid() {
638ThreadID GetTid() {
639639# if SANITIZER_FREEBSD
640640 long Tid;
641641 thr_self(&Tid);
......@@ -649,7 +649,7 @@ tid_t GetTid() {
649649# endif
650650}
651651
652int TgKill(pid_t pid, tid_t tid, int sig) {
652int TgKill(pid_t pid, ThreadID tid, int sig) {
653653# if SANITIZER_LINUX
654654 return internal_syscall(SYSCALL(tgkill), pid, tid, sig);
655655# elif SANITIZER_FREEBSD
......@@ -1091,7 +1091,7 @@ ThreadLister::ThreadLister(pid_t pid) : buffer_(4096) {
10911091}
10921092
10931093ThreadLister::Result ThreadLister::ListThreads(
1094 InternalMmapVector<tid_t> *threads) {
1094 InternalMmapVector<ThreadID> *threads) {
10951095 int descriptor = internal_open(task_path_.data(), O_RDONLY | O_DIRECTORY);
10961096 if (internal_iserror(descriptor)) {
10971097 Report("Can't open %s for reading.\n", task_path_.data());
......@@ -1146,7 +1146,7 @@ ThreadLister::Result ThreadLister::ListThreads(
11461146 }
11471147}
11481148
1149const char *ThreadLister::LoadStatus(tid_t tid) {
1149const char *ThreadLister::LoadStatus(ThreadID tid) {
11501150 status_path_.clear();
11511151 status_path_.AppendF("%s/%llu/status", task_path_.data(), tid);
11521152 auto cleanup = at_scope_exit([&] {
......@@ -1159,7 +1159,7 @@ const char *ThreadLister::LoadStatus(tid_t tid) {
11591159 return buffer_.data();
11601160}
11611161
1162bool ThreadLister::IsAlive(tid_t tid) {
1162bool ThreadLister::IsAlive(ThreadID tid) {
11631163 // /proc/%d/task/%d/status uses same call to detect alive threads as
11641164 // proc_task_readdir. See task_state implementation in Linux.
11651165 static const char kPrefix[] = "\nPPid:";
......@@ -1289,7 +1289,7 @@ uptr GetPageSize() {
12891289
12901290uptr ReadBinaryName(/*out*/ char *buf, uptr buf_len) {
12911291# if SANITIZER_HAIKU
1292 int cookie = 0;
1292 int32 cookie = 0;
12931293 image_info info;
12941294 const char *argv0 = "<UNKNOWN>";
12951295 while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) {
......@@ -1989,7 +1989,10 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
19891989# elif SANITIZER_NETBSD
19901990 uptr err = ucontext->uc_mcontext.__gregs[_REG_ERR];
19911991# elif SANITIZER_HAIKU
1992 uptr err = ucontext->uc_mcontext.r13;
1992 uptr err = 0; // FIXME: ucontext->uc_mcontext.r13;
1993 // The err register was added on the main branch and not
1994 // available with the current release. To be reverted later.
1995 // https://github.com/haiku/haiku/commit/11adda21aa4e6b24f71a496868a44d7607bc3764
19931996# elif SANITIZER_SOLARIS && defined(__i386__)
19941997 const int Err = 13;
19951998 uptr err = ucontext->uc_mcontext.gregs[Err];
......@@ -2619,6 +2622,11 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
26192622 *pc = ucontext->uc_mcontext.mc_eip;
26202623 *bp = ucontext->uc_mcontext.mc_ebp;
26212624 *sp = ucontext->uc_mcontext.mc_esp;
2625# elif SANITIZER_HAIKU
2626 ucontext_t *ucontext = (ucontext_t *)context;
2627 *pc = ucontext->uc_mcontext.eip;
2628 *bp = ucontext->uc_mcontext.ebp;
2629 *sp = ucontext->uc_mcontext.esp;
26222630# else
26232631 ucontext_t *ucontext = (ucontext_t *)context;
26242632# if SANITIZER_SOLARIS
lib/libtsan/sanitizer_common/sanitizer_linux.h+3-3
......@@ -108,11 +108,11 @@ class ThreadLister {
108108 Incomplete,
109109 Ok,
110110 };
111 Result ListThreads(InternalMmapVector<tid_t> *threads);
112 const char *LoadStatus(tid_t tid);
111 Result ListThreads(InternalMmapVector<ThreadID> *threads);
112 const char *LoadStatus(ThreadID tid);
113113
114114 private:
115 bool IsAlive(tid_t tid);
115 bool IsAlive(ThreadID tid);
116116
117117 InternalScopedString task_path_;
118118 InternalScopedString status_path_;
lib/libtsan/sanitizer_common/sanitizer_linux_libcdep.cpp+1
......@@ -29,6 +29,7 @@
2929# include "sanitizer_solaris.h"
3030
3131# if SANITIZER_HAIKU
32# define _GNU_SOURCE
3233# define _DEFAULT_SOURCE
3334# endif
3435
lib/libtsan/sanitizer_common/sanitizer_mac.cpp+255-104
......@@ -22,6 +22,11 @@
2222# endif
2323# include <stdio.h>
2424
25// Start searching for available memory region past PAGEZERO, which is
26// 4KB on 32-bit and 4GB on 64-bit.
27# define GAP_SEARCH_START_ADDRESS \
28 ((SANITIZER_WORDSIZE == 32) ? 0x000000001000 : 0x000100000000)
29
2530# include "sanitizer_common.h"
2631# include "sanitizer_file.h"
2732# include "sanitizer_flags.h"
......@@ -58,9 +63,11 @@ extern char ***_NSGetArgv(void);
5863# include <dlfcn.h> // for dladdr()
5964# include <errno.h>
6065# include <fcntl.h>
66# include <inttypes.h>
6167# include <libkern/OSAtomic.h>
6268# include <mach-o/dyld.h>
6369# include <mach/mach.h>
70# include <mach/mach_error.h>
6471# include <mach/mach_time.h>
6572# include <mach/vm_statistics.h>
6673# include <malloc/malloc.h>
......@@ -96,8 +103,16 @@ extern "C" {
96103 natural_t *nesting_depth,
97104 vm_region_recurse_info_t info,
98105 mach_msg_type_number_t *infoCnt);
106
107 extern const void* _dyld_get_shared_cache_range(size_t* length);
99108}
100109
110# if !SANITIZER_GO
111// Weak symbol no-op when TSan is not linked
112SANITIZER_WEAK_ATTRIBUTE extern void __tsan_set_in_internal_write_call(
113 bool value) {}
114# endif
115
101116namespace __sanitizer {
102117
103118#include "sanitizer_syscall_generic.inc"
......@@ -168,7 +183,15 @@ uptr internal_read(fd_t fd, void *buf, uptr count) {
168183}
169184
170185uptr internal_write(fd_t fd, const void *buf, uptr count) {
186# if SANITIZER_GO
171187 return write(fd, buf, count);
188# else
189 // We need to disable interceptors when writing in TSan
190 __tsan_set_in_internal_write_call(true);
191 uptr res = write(fd, buf, count);
192 __tsan_set_in_internal_write_call(false);
193 return res;
194# endif
172195}
173196
174197uptr internal_stat(const char *path, void *buf) {
......@@ -258,53 +281,43 @@ int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
258281 (size_t)newlen);
259282}
260283
261static fd_t internal_spawn_impl(const char *argv[], const char *envp[],
262 pid_t *pid) {
263 fd_t primary_fd = kInvalidFd;
264 fd_t secondary_fd = kInvalidFd;
284bool internal_spawn(const char* argv[], const char* envp[], pid_t* pid,
285 fd_t fd_stdin, fd_t fd_stdout) {
286 // NOTE: Caller ensures that fd_stdin and fd_stdout are not 0, 1, or 2, since
287 // this can break communication.
288 //
289 // NOTE: Caller is responsible for closing fd_stdin after the process has
290 // died.
265291
292 int res;
266293 auto fd_closer = at_scope_exit([&] {
267 internal_close(primary_fd);
268 internal_close(secondary_fd);
294 // NOTE: We intentionally do not close fd_stdin since this can
295 // cause us to receive a fatal SIGPIPE if the process dies.
296 internal_close(fd_stdout);
269297 });
270298
271 // We need a new pseudoterminal to avoid buffering problems. The 'atos' tool
272 // in particular detects when it's talking to a pipe and forgets to flush the
273 // output stream after sending a response.
274 primary_fd = posix_openpt(O_RDWR);
275 if (primary_fd == kInvalidFd)
276 return kInvalidFd;
277
278 int res = grantpt(primary_fd) || unlockpt(primary_fd);
279 if (res != 0) return kInvalidFd;
280
281 // Use TIOCPTYGNAME instead of ptsname() to avoid threading problems.
282 char secondary_pty_name[128];
283 res = ioctl(primary_fd, TIOCPTYGNAME, secondary_pty_name);
284 if (res == -1) return kInvalidFd;
285
286 secondary_fd = internal_open(secondary_pty_name, O_RDWR);
287 if (secondary_fd == kInvalidFd)
288 return kInvalidFd;
289
290299 // File descriptor actions
291300 posix_spawn_file_actions_t acts;
292301 res = posix_spawn_file_actions_init(&acts);
293 if (res != 0) return kInvalidFd;
302 if (res != 0)
303 return false;
294304
295305 auto acts_cleanup = at_scope_exit([&] {
296306 posix_spawn_file_actions_destroy(&acts);
297307 });
298308
299 res = posix_spawn_file_actions_adddup2(&acts, secondary_fd, STDIN_FILENO) ||
300 posix_spawn_file_actions_adddup2(&acts, secondary_fd, STDOUT_FILENO) ||
301 posix_spawn_file_actions_addclose(&acts, secondary_fd);
302 if (res != 0) return kInvalidFd;
309 res = posix_spawn_file_actions_adddup2(&acts, fd_stdin, STDIN_FILENO) ||
310 posix_spawn_file_actions_adddup2(&acts, fd_stdout, STDOUT_FILENO) ||
311 posix_spawn_file_actions_addclose(&acts, fd_stdin) ||
312 posix_spawn_file_actions_addclose(&acts, fd_stdout);
313 if (res != 0)
314 return false;
303315
304316 // Spawn attributes
305317 posix_spawnattr_t attrs;
306318 res = posix_spawnattr_init(&attrs);
307 if (res != 0) return kInvalidFd;
319 if (res != 0)
320 return false;
308321
309322 auto attrs_cleanup = at_scope_exit([&] {
310323 posix_spawnattr_destroy(&attrs);
......@@ -313,50 +326,17 @@ static fd_t internal_spawn_impl(const char *argv[], const char *envp[],
313326 // In the spawned process, close all file descriptors that are not explicitly
314327 // described by the file actions object. This is Darwin-specific extension.
315328 res = posix_spawnattr_setflags(&attrs, POSIX_SPAWN_CLOEXEC_DEFAULT);
316 if (res != 0) return kInvalidFd;
329 if (res != 0)
330 return false;
317331
318332 // posix_spawn
319333 char **argv_casted = const_cast<char **>(argv);
320334 char **envp_casted = const_cast<char **>(envp);
321335 res = posix_spawn(pid, argv[0], &acts, &attrs, argv_casted, envp_casted);
322 if (res != 0) return kInvalidFd;
323
324 // Disable echo in the new terminal, disable CR.
325 struct termios termflags;
326 tcgetattr(primary_fd, &termflags);
327 termflags.c_oflag &= ~ONLCR;
328 termflags.c_lflag &= ~ECHO;
329 tcsetattr(primary_fd, TCSANOW, &termflags);
330
331 // On success, do not close primary_fd on scope exit.
332 fd_t fd = primary_fd;
333 primary_fd = kInvalidFd;
334
335 return fd;
336}
337
338fd_t internal_spawn(const char *argv[], const char *envp[], pid_t *pid) {
339 // The client program may close its stdin and/or stdout and/or stderr thus
340 // allowing open/posix_openpt to reuse file descriptors 0, 1 or 2. In this
341 // case the communication is broken if either the parent or the child tries to
342 // close or duplicate these descriptors. We temporarily reserve these
343 // descriptors here to prevent this.
344 fd_t low_fds[3];
345 size_t count = 0;
346
347 for (; count < 3; count++) {
348 low_fds[count] = posix_openpt(O_RDWR);
349 if (low_fds[count] >= STDERR_FILENO)
350 break;
351 }
352
353 fd_t fd = internal_spawn_impl(argv, envp, pid);
354
355 for (; count > 0; count--) {
356 internal_close(low_fds[count]);
357 }
336 if (res != 0)
337 return false;
358338
359 return fd;
339 return true;
360340}
361341
362342uptr internal_rename(const char *oldpath, const char *newpath) {
......@@ -394,8 +374,8 @@ bool DirExists(const char *path) {
394374 return S_ISDIR(st.st_mode);
395375}
396376
397tid_t GetTid() {
398 tid_t tid;
377ThreadID GetTid() {
378 ThreadID tid;
399379 pthread_threadid_np(nullptr, &tid);
400380 return tid;
401381}
......@@ -769,11 +749,17 @@ void internal_join_thread(void *th) { pthread_join((pthread_t)th, 0); }
769749static Mutex syslog_lock;
770750# endif
771751
752# if SANITIZER_DRIVERKIT
753# define SANITIZER_OS_LOG os_log
754# else
755# define SANITIZER_OS_LOG os_log_error
756# endif
757
772758void WriteOneLineToSyslog(const char *s) {
773759#if !SANITIZER_GO
774760 syslog_lock.CheckLocked();
775761 if (GetMacosAlignedVersion() >= MacosVersion(10, 12)) {
776 os_log_error(OS_LOG_DEFAULT, "%{public}s", s);
762 SANITIZER_OS_LOG(OS_LOG_DEFAULT, "%{public}s", s);
777763 } else {
778764#pragma clang diagnostic push
779765// as_log is deprecated.
......@@ -837,22 +823,22 @@ void LogMessageOnPrintf(const char *str) {
837823
838824void LogFullErrorReport(const char *buffer) {
839825# if !SANITIZER_GO
840 // Log with os_log_error. This will make it into the crash log.
826 // When logging with os_log_error this will make it into the crash log.
841827 if (internal_strncmp(SanitizerToolName, "AddressSanitizer",
842828 sizeof("AddressSanitizer") - 1) == 0)
843 os_log_error(OS_LOG_DEFAULT, "Address Sanitizer reported a failure.");
829 SANITIZER_OS_LOG(OS_LOG_DEFAULT, "Address Sanitizer reported a failure.");
844830 else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer",
845831 sizeof("UndefinedBehaviorSanitizer") - 1) == 0)
846 os_log_error(OS_LOG_DEFAULT,
847 "Undefined Behavior Sanitizer reported a failure.");
832 SANITIZER_OS_LOG(OS_LOG_DEFAULT,
833 "Undefined Behavior Sanitizer reported a failure.");
848834 else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer",
849835 sizeof("ThreadSanitizer") - 1) == 0)
850 os_log_error(OS_LOG_DEFAULT, "Thread Sanitizer reported a failure.");
836 SANITIZER_OS_LOG(OS_LOG_DEFAULT, "Thread Sanitizer reported a failure.");
851837 else
852 os_log_error(OS_LOG_DEFAULT, "Sanitizer tool reported a failure.");
838 SANITIZER_OS_LOG(OS_LOG_DEFAULT, "Sanitizer tool reported a failure.");
853839
854840 if (common_flags()->log_to_syslog)
855 os_log_error(OS_LOG_DEFAULT, "Consult syslog for more information.");
841 SANITIZER_OS_LOG(OS_LOG_DEFAULT, "Consult syslog for more information.");
856842
857843 // Log to syslog.
858844 // The logging on OS X may call pthread_create so we need the threading
......@@ -933,7 +919,17 @@ static void DisableMmapExcGuardExceptions() {
933919 RTLD_DEFAULT, "task_set_exc_guard_behavior");
934920 if (set_behavior == nullptr) return;
935921 const task_exc_guard_behavior_t task_exc_guard_none = 0;
936 set_behavior(mach_task_self(), task_exc_guard_none);
922 kern_return_t res = set_behavior(mach_task_self(), task_exc_guard_none);
923 if (res != KERN_SUCCESS) {
924 Report(
925 "WARN: task_set_exc_guard_behavior returned %d (%s), "
926 "mmap may fail unexpectedly.\n",
927 res, mach_error_string(res));
928 if (res == KERN_DENIED)
929 Report(
930 "HINT: Check that task_set_exc_guard_behavior is allowed by "
931 "sandbox.\n");
932 }
937933}
938934
939935static void VerifyInterceptorsWorking();
......@@ -1100,6 +1096,67 @@ static void StripEnv() {
11001096}
11011097#endif // SANITIZER_GO
11021098
1099// Prints out a consolidated memory map: contiguous regions
1100// are merged together.
1101static void PrintVmmap() {
1102 const mach_vm_address_t max_vm_address = GetMaxVirtualAddress() + 1;
1103 mach_vm_address_t address = GAP_SEARCH_START_ADDRESS;
1104 kern_return_t kr = KERN_SUCCESS;
1105
1106 Report("Memory map:\n");
1107 mach_vm_address_t last = 0;
1108 mach_vm_address_t lastsz = 0;
1109
1110 while (1) {
1111 mach_vm_size_t vmsize = 0;
1112 natural_t depth = 0;
1113 vm_region_submap_short_info_data_64_t vminfo;
1114 mach_msg_type_number_t count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
1115 kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth,
1116 (vm_region_info_t)&vminfo, &count);
1117
1118 if (kr == KERN_DENIED) {
1119 Report(
1120 "ERROR: mach_vm_region_recurse got KERN_DENIED when printing memory "
1121 "map.\n");
1122 Report(
1123 "HINT: Check whether mach_vm_region_recurse is allowed by "
1124 "sandbox.\n");
1125 }
1126
1127 if (kr == KERN_SUCCESS && address < max_vm_address) {
1128 if (last + lastsz == address) {
1129 // This region is contiguous with the last; merge together.
1130 lastsz += vmsize;
1131 } else {
1132 if (lastsz)
1133 Printf("|| `[%p, %p]` || size=0x%016" PRIx64 " ||\n", (void*)last,
1134 (void*)(last + lastsz), lastsz);
1135
1136 last = address;
1137 lastsz = vmsize;
1138 }
1139 address += vmsize;
1140 } else {
1141 // We've reached the end of the memory map. Print the last remaining
1142 // region, if there is one.
1143 if (lastsz)
1144 Printf("|| `[%p, %p]` || size=0x%016" PRIx64 " ||\n", (void*)last,
1145 (void*)(last + lastsz), lastsz);
1146
1147 break;
1148 }
1149 }
1150}
1151
1152static void ReportShadowAllocFail(uptr shadow_size_bytes, uptr alignment) {
1153 Report(
1154 "FATAL: Failed to allocate shadow memory. Tried to allocate %p bytes "
1155 "(alignment=%p).\n",
1156 (void*)shadow_size_bytes, (void*)alignment);
1157 PrintVmmap();
1158}
1159
11031160char **GetArgv() {
11041161 return *_NSGetArgv();
11051162}
......@@ -1207,10 +1264,11 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
12071264 if (new_max_vm < max_occupied_addr) {
12081265 Report("Unable to find a memory range for dynamic shadow.\n");
12091266 Report(
1210 "space_size = %p, largest_gap_found = %p, max_occupied_addr = %p, "
1211 "new_max_vm = %p\n",
1212 (void *)space_size, (void *)largest_gap_found,
1213 (void *)max_occupied_addr, (void *)new_max_vm);
1267 "\tspace_size = %p\n\tlargest_gap_found = %p\n\tmax_occupied_addr "
1268 "= %p\n\tnew_max_vm = %p\n",
1269 (void*)space_size, (void*)largest_gap_found, (void*)max_occupied_addr,
1270 (void*)new_max_vm);
1271 ReportShadowAllocFail(shadow_size_bytes, alignment);
12141272 CHECK(0 && "cannot place shadow");
12151273 }
12161274 RestrictMemoryToMaxAddress(new_max_vm);
......@@ -1221,6 +1279,7 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
12211279 nullptr, nullptr);
12221280 if (shadow_start == 0) {
12231281 Report("Unable to find a memory range after restricting VM.\n");
1282 ReportShadowAllocFail(shadow_size_bytes, alignment);
12241283 CHECK(0 && "cannot place shadow after restricting vm");
12251284 }
12261285 }
......@@ -1229,6 +1288,25 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
12291288 return shadow_start;
12301289}
12311290
1291// Returns a list of ranges which must be covered by shadow memory,
1292// and cannot overlap with any fixed mappings made by a sanitizer.
1293// This can ensure that the sanitizer runtime does not map over
1294// platform-reserved regions.
1295void GetAppReservedRanges(InternalMmapVector<ReservedRange>& ranges) {
1296 ranges.clear();
1297
1298# if SANITIZER_OSX
1299 // On macOS, the first 512GB are platform-reserved (some of which
1300 // may also be available to applications).
1301 ranges.push_back({0x1000UL, 0x8000000000UL});
1302# endif
1303
1304 VReport(2, "App ranges:\n");
1305 for (auto& [range_start, range_end] : ranges) {
1306 VReport(2, " [%p, %p]\n", range_start, range_end);
1307 }
1308}
1309
12321310uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size,
12331311 uptr num_aliases, uptr ring_buffer_size) {
12341312 CHECK(false && "HWASan aliasing is unimplemented on Mac");
......@@ -1236,40 +1314,61 @@ uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size,
12361314}
12371315
12381316uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
1239 uptr *largest_gap_found,
1240 uptr *max_occupied_addr) {
1241 typedef vm_region_submap_short_info_data_64_t RegionInfo;
1242 enum { kRegionInfoSize = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 };
1243 // Start searching for available memory region past PAGEZERO, which is
1244 // 4KB on 32-bit and 4GB on 64-bit.
1245 mach_vm_address_t start_address =
1246 (SANITIZER_WORDSIZE == 32) ? 0x000000001000 : 0x000100000000;
1247
1317 uptr* largest_gap_found,
1318 uptr* max_occupied_addr) {
12481319 const mach_vm_address_t max_vm_address = GetMaxVirtualAddress() + 1;
1249 mach_vm_address_t address = start_address;
1250 mach_vm_address_t free_begin = start_address;
1320 mach_vm_address_t address = GAP_SEARCH_START_ADDRESS;
1321 mach_vm_address_t free_begin = GAP_SEARCH_START_ADDRESS;
1322
1323 // Restrict the search to be after any reserved ranges
1324 InternalMmapVector<ReservedRange> app_ranges;
1325 GetAppReservedRanges(app_ranges);
1326
1327 for (auto& [range_start, range_end] : app_ranges) {
1328 address = Max(address, (mach_vm_address_t)range_end);
1329 free_begin = Max(free_begin, (mach_vm_address_t)range_end);
1330 }
1331
12511332 kern_return_t kr = KERN_SUCCESS;
12521333 if (largest_gap_found) *largest_gap_found = 0;
12531334 if (max_occupied_addr) *max_occupied_addr = 0;
12541335 while (kr == KERN_SUCCESS) {
12551336 mach_vm_size_t vmsize = 0;
12561337 natural_t depth = 0;
1257 RegionInfo vminfo;
1258 mach_msg_type_number_t count = kRegionInfoSize;
1338 vm_region_submap_short_info_data_64_t vminfo;
1339 mach_msg_type_number_t count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
12591340 kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth,
12601341 (vm_region_info_t)&vminfo, &count);
12611342
1262 // There are cases where going beyond the processes' max vm does
1263 // not return KERN_INVALID_ADDRESS so we check for going beyond that
1264 // max address as well.
1265 if (kr == KERN_INVALID_ADDRESS || address > max_vm_address) {
1343 if (kr == KERN_SUCCESS) {
1344 // There are cases where going beyond the processes' max vm does
1345 // not return KERN_INVALID_ADDRESS so we check for going beyond that
1346 // max address as well.
1347 if (address > max_vm_address) {
1348 address = max_vm_address;
1349 kr = -1; // break after this iteration.
1350 }
1351
1352 if (max_occupied_addr)
1353 *max_occupied_addr = address + vmsize;
1354 } else if (kr == KERN_INVALID_ADDRESS) {
12661355 // No more regions beyond "address", consider the gap at the end of VM.
12671356 address = max_vm_address;
1268 vmsize = 0;
1269 kr = -1; // break after this iteration.
1357
1358 // We will break after this iteration anyway since kr != KERN_SUCCESS
1359 } else if (kr == KERN_DENIED) {
1360 Report("ERROR: Unable to find a memory range for dynamic shadow.\n");
1361 Report("HINT: Ensure mach_vm_region_recurse is allowed under sandbox.\n");
1362 Die();
12701363 } else {
1271 if (max_occupied_addr) *max_occupied_addr = address + vmsize;
1364 Report(
1365 "WARNING: mach_vm_region_recurse returned unexpected code %d (%s)\n",
1366 kr, mach_error_string(kr));
1367 DCHECK(false && "mach_vm_region_recurse returned unexpected code");
1368 break; // address is not valid unless KERN_SUCCESS, therefore we must not
1369 // use it.
12721370 }
1371
12731372 if (free_begin != address) {
12741373 // We found a free region [free_begin..address-1].
12751374 uptr gap_start = RoundUpTo((uptr)free_begin + left_padding, alignment);
......@@ -1292,6 +1391,58 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
12921391 return 0;
12931392}
12941393
1394// This function (when used during initialization when there is
1395// only a single thread), can be used to verify that a range
1396// of memory hasn't already been mapped, and won't be mapped
1397// later in the shared cache.
1398//
1399// If the syscall mach_vm_region_recurse fails (due to sandbox),
1400// we assume that the memory is not mapped so that execution can continue.
1401//
1402// NOTE: range_end is inclusive
1403//
1404// WARNING: This function must NOT allocate memory, since it is
1405// used in InitializeShadowMemory between where we search for
1406// space for shadow and where we actually allocate it.
1407bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
1408 mach_vm_size_t vmsize = 0;
1409 natural_t depth = 0;
1410 vm_region_submap_short_info_data_64_t vminfo;
1411 mach_msg_type_number_t count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
1412 mach_vm_address_t address = range_start;
1413
1414 // First, check if the range is already mapped.
1415 kern_return_t kr =
1416 mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth,
1417 (vm_region_info_t)&vminfo, &count);
1418
1419 if (kr == KERN_DENIED) {
1420 Report(
1421 "WARN: mach_vm_region_recurse returned KERN_DENIED when checking "
1422 "whether an address is mapped.\n");
1423 Report("HINT: Is mach_vm_region_recurse allowed by sandbox?\n");
1424 }
1425
1426 if (kr == KERN_SUCCESS && !IntervalsAreSeparate(address, address + vmsize - 1,
1427 range_start, range_end)) {
1428 // Overlaps with already-mapped memory
1429 return false;
1430 }
1431
1432 size_t cacheLength;
1433 uptr cacheStart = (uptr)_dyld_get_shared_cache_range(&cacheLength);
1434
1435 if (cacheStart &&
1436 !IntervalsAreSeparate(cacheStart, cacheStart + cacheLength - 1,
1437 range_start, range_end)) {
1438 // Overlaps with shared cache region
1439 return false;
1440 }
1441
1442 // We believe this address is available.
1443 return true;
1444}
1445
12951446// FIXME implement on this platform.
12961447void GetMemoryProfile(fill_profile_f cb, uptr *stats) {}
12971448
lib/libtsan/sanitizer_common/sanitizer_mac.h+5
......@@ -58,8 +58,13 @@ struct DarwinKernelVersion : VersionBase<DarwinKernelVersion> {
5858 DarwinKernelVersion(u16 major, u16 minor) : VersionBase(major, minor) {}
5959};
6060
61struct ReservedRange {
62 uptr beg, end;
63};
64
6165MacosVersion GetMacosAlignedVersion();
6266DarwinKernelVersion GetDarwinKernelVersion();
67void GetAppReservedRanges(InternalMmapVector<ReservedRange>& ranges);
6368
6469char **GetEnviron();
6570
lib/libtsan/sanitizer_common/sanitizer_netbsd.cpp+2-2
......@@ -229,12 +229,12 @@ uptr internal_execve(const char *filename, char *const argv[],
229229 return _sys_execve(filename, argv, envp);
230230}
231231
232tid_t GetTid() {
232ThreadID GetTid() {
233233 DEFINE__REAL(int, _lwp_self);
234234 return _REAL(_lwp_self);
235235}
236236
237int TgKill(pid_t pid, tid_t tid, int sig) {
237int TgKill(pid_t pid, ThreadID tid, int sig) {
238238 DEFINE__REAL(int, _lwp_kill, int a, int b);
239239 (void)pid;
240240 return _REAL(_lwp_kill, tid, sig);
lib/libtsan/sanitizer_common/sanitizer_platform.h+27-1
......@@ -319,7 +319,11 @@
319319#endif
320320
321321// The first address that can be returned by mmap.
322#define SANITIZER_MMAP_BEGIN 0
322#if SANITIZER_AIX && SANITIZER_WORDSIZE == 64
323# define SANITIZER_MMAP_BEGIN 0x0a00'0000'0000'0000ULL
324#else
325# define SANITIZER_MMAP_BEGIN 0
326#endif
323327
324328// The range of addresses which can be returned my mmap.
325329// FIXME: this value should be different on different platforms. Larger values
......@@ -482,4 +486,26 @@
482486# define SANITIZER_START_BACKGROUND_THREAD_IN_ASAN_INTERNAL 0
483487#endif
484488
489#if SANITIZER_LINUX
490# if SANITIZER_GLIBC
491// Workaround for
492// glibc/commit/3d3572f59059e2b19b8541ea648a6172136ec42e
493// Linux: Keep termios ioctl constants strictly internal
494# if __GLIBC_PREREQ(2, 41)
495# define SANITIZER_TERMIOS_IOCTL_CONSTANTS 0
496# else
497# define SANITIZER_TERMIOS_IOCTL_CONSTANTS 1
498# endif
499# else
500# define SANITIZER_TERMIOS_IOCTL_CONSTANTS 1
501# endif
502#endif
503
504#if SANITIZER_APPLE && SANITIZER_WORDSIZE == 64
505// MTE uses the lower half of the top byte.
506# define STRIP_MTE_TAG(addr) ((addr) & ~((uptr)0x0f << 56))
507#else
508# define STRIP_MTE_TAG(addr) (addr)
509#endif
510
485511#endif // SANITIZER_PLATFORM_H
lib/libtsan/sanitizer_common/sanitizer_platform_interceptors.h+5-4
......@@ -167,7 +167,7 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
167167
168168#define SANITIZER_INTERCEPT_STRLEN SI_NOT_FUCHSIA
169169#define SANITIZER_INTERCEPT_STRNLEN (SI_NOT_MAC && SI_NOT_FUCHSIA)
170#define SANITIZER_INTERCEPT_STRCMP (SI_NOT_FUCHSIA && SI_NOT_AIX)
170#define SANITIZER_INTERCEPT_STRCMP SI_NOT_FUCHSIA
171171#define SANITIZER_INTERCEPT_STRSTR SI_NOT_FUCHSIA
172172#define SANITIZER_INTERCEPT_STRCASESTR (SI_POSIX && SI_NOT_AIX)
173173#define SANITIZER_INTERCEPT_STRTOK SI_NOT_FUCHSIA
......@@ -179,8 +179,8 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
179179#define SANITIZER_INTERCEPT_TEXTDOMAIN SI_LINUX_NOT_ANDROID || SI_SOLARIS
180180#define SANITIZER_INTERCEPT_STRCASECMP SI_POSIX
181181#define SANITIZER_INTERCEPT_MEMSET 1
182#define SANITIZER_INTERCEPT_MEMMOVE SI_NOT_AIX
183#define SANITIZER_INTERCEPT_MEMCPY SI_NOT_AIX
182#define SANITIZER_INTERCEPT_MEMMOVE 1
183#define SANITIZER_INTERCEPT_MEMCPY 1
184184#define SANITIZER_INTERCEPT_MEMCMP SI_NOT_FUCHSIA
185185#define SANITIZER_INTERCEPT_BCMP \
186186 SANITIZER_INTERCEPT_MEMCMP && \
......@@ -551,7 +551,8 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
551551#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_NETBSD)
552552#define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID
553553#define SANITIZER_INTERCEPT_WCSLEN 1
554#define SANITIZER_INTERCEPT_WCSCAT SI_POSIX
554#define SANITIZER_INTERCEPT_WCSNLEN 1
555#define SANITIZER_INTERCEPT_WCSCAT (SI_POSIX || SI_WINDOWS)
555556#define SANITIZER_INTERCEPT_WCSDUP SI_POSIX
556557#define SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION (!SI_WINDOWS && SI_NOT_FUCHSIA)
557558#define SANITIZER_INTERCEPT_BSD_SIGNAL SI_ANDROID
lib/libtsan/sanitizer_common/sanitizer_platform_limits_posix.cpp+4-4
......@@ -779,16 +779,16 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
779779 unsigned IOCTL_SOUND_PCM_WRITE_FILTER = SOUND_PCM_WRITE_FILTER;
780780#endif // SOUND_VERSION
781781 unsigned IOCTL_TCFLSH = TCFLSH;
782 unsigned IOCTL_TCGETA = TCGETA;
782# if SANITIZER_TERMIOS_IOCTL_CONSTANTS
783783 unsigned IOCTL_TCGETS = TCGETS;
784# endif
784785 unsigned IOCTL_TCSBRK = TCSBRK;
785786 unsigned IOCTL_TCSBRKP = TCSBRKP;
786 unsigned IOCTL_TCSETA = TCSETA;
787 unsigned IOCTL_TCSETAF = TCSETAF;
788 unsigned IOCTL_TCSETAW = TCSETAW;
787# if SANITIZER_TERMIOS_IOCTL_CONSTANTS
789788 unsigned IOCTL_TCSETS = TCSETS;
790789 unsigned IOCTL_TCSETSF = TCSETSF;
791790 unsigned IOCTL_TCSETSW = TCSETSW;
791# endif
792792 unsigned IOCTL_TCXONC = TCXONC;
793793 unsigned IOCTL_TIOCGLCKTRMIOS = TIOCGLCKTRMIOS;
794794 unsigned IOCTL_TIOCGSOFTCAR = TIOCGSOFTCAR;
lib/libtsan/sanitizer_common/sanitizer_platform_limits_posix.h+32-6
......@@ -32,6 +32,8 @@
3232# elif SANITIZER_GLIBC || SANITIZER_ANDROID
3333# define SANITIZER_HAS_STAT64 1
3434# define SANITIZER_HAS_STATFS64 1
35# elif SANITIZER_HAIKU
36# include <stdint.h>
3537# endif
3638
3739# if defined(__sparc__)
......@@ -102,6 +104,8 @@ const unsigned struct_kernel_stat_sz = SANITIZER_ANDROID
102104 ? FIRST_32_SECOND_64(104, 128)
103105# if defined(_ABIN32) && _MIPS_SIM == _ABIN32
104106 : FIRST_32_SECOND_64(176, 216);
107# elif SANITIZER_MUSL
108 : FIRST_32_SECOND_64(160, 208);
105109# else
106110 : FIRST_32_SECOND_64(160, 216);
107111# endif
......@@ -476,6 +480,30 @@ struct __sanitizer_cmsghdr {
476480 int cmsg_level;
477481 int cmsg_type;
478482};
483# elif SANITIZER_MUSL
484struct __sanitizer_msghdr {
485 void *msg_name;
486 unsigned msg_namelen;
487 struct __sanitizer_iovec *msg_iov;
488 int msg_iovlen;
489# if SANITIZER_WORDSIZE == 64
490 int __pad1;
491# endif
492 void *msg_control;
493 unsigned msg_controllen;
494# if SANITIZER_WORDSIZE == 64
495 int __pad2;
496# endif
497 int msg_flags;
498};
499struct __sanitizer_cmsghdr {
500 unsigned cmsg_len;
501# if SANITIZER_WORDSIZE == 64
502 int __pad1;
503# endif
504 int cmsg_level;
505 int cmsg_type;
506};
479507# else
480508// In POSIX, int msg_iovlen; socklen_t msg_controllen; socklen_t cmsg_len; but
481509// many implementations don't conform to the standard.
......@@ -603,7 +631,7 @@ typedef unsigned long __sanitizer_sigset_t;
603631# elif SANITIZER_APPLE
604632typedef unsigned __sanitizer_sigset_t;
605633# elif SANITIZER_HAIKU
606typedef unsigned long __sanitizer_sigset_t;
634typedef uint64_t __sanitizer_sigset_t;
607635# elif SANITIZER_LINUX
608636struct __sanitizer_sigset_t {
609637 // The size is determined by looking at sizeof of real sigset_t on linux.
......@@ -1312,16 +1340,14 @@ extern unsigned IOCTL_SNDCTL_COPR_SENDMSG;
13121340extern unsigned IOCTL_SNDCTL_COPR_WCODE;
13131341extern unsigned IOCTL_SNDCTL_COPR_WDATA;
13141342extern unsigned IOCTL_TCFLSH;
1315extern unsigned IOCTL_TCGETA;
1316extern unsigned IOCTL_TCGETS;
13171343extern unsigned IOCTL_TCSBRK;
13181344extern unsigned IOCTL_TCSBRKP;
1319extern unsigned IOCTL_TCSETA;
1320extern unsigned IOCTL_TCSETAF;
1321extern unsigned IOCTL_TCSETAW;
1345# if SANITIZER_TERMIOS_IOCTL_CONSTANTS
1346extern unsigned IOCTL_TCGETS;
13221347extern unsigned IOCTL_TCSETS;
13231348extern unsigned IOCTL_TCSETSF;
13241349extern unsigned IOCTL_TCSETSW;
1350# endif
13251351extern unsigned IOCTL_TCXONC;
13261352extern unsigned IOCTL_TIOCGLCKTRMIOS;
13271353extern unsigned IOCTL_TIOCGSOFTCAR;
lib/libtsan/sanitizer_common/sanitizer_posix.cpp+3-12
......@@ -225,17 +225,9 @@ void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset) {
225225 return (void *)p;
226226}
227227
228static inline bool IntervalsAreSeparate(uptr start1, uptr end1,
229 uptr start2, uptr end2) {
230 CHECK(start1 <= end1);
231 CHECK(start2 <= end2);
232 return (end1 < start2) || (end2 < start1);
233}
234
228# if !SANITIZER_APPLE
235229// FIXME: this is thread-unsafe, but should not cause problems most of the time.
236// When the shadow is mapped only a single thread usually exists (plus maybe
237// several worker threads on Mac, which aren't expected to map big chunks of
238// memory).
230// When the shadow is mapped only a single thread usually exists
239231bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
240232 MemoryMappingLayout proc_maps(/*cache_enabled*/true);
241233 if (proc_maps.Error())
......@@ -251,7 +243,6 @@ bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
251243 return true;
252244}
253245
254#if !SANITIZER_APPLE
255246void DumpProcessMap() {
256247 MemoryMappingLayout proc_maps(/*cache_enabled*/true);
257248 const sptr kBufSize = 4095;
......@@ -265,7 +256,7 @@ void DumpProcessMap() {
265256 Report("End of process memory map.\n");
266257 UnmapOrDie(filename, kBufSize);
267258}
268#endif
259# endif
269260
270261const char *GetPwd() {
271262 return GetEnv("PWD");
lib/libtsan/sanitizer_common/sanitizer_posix.h+2-1
......@@ -67,7 +67,8 @@ uptr internal_ptrace(int request, int pid, void *addr, void *data);
6767uptr internal_waitpid(int pid, int *status, int options);
6868
6969int internal_fork();
70fd_t internal_spawn(const char *argv[], const char *envp[], pid_t *pid);
70bool internal_spawn(const char* argv[], const char* envp[], pid_t* pid,
71 fd_t fd_stdin, fd_t fd_stdout);
7172
7273int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
7374 uptr *oldlenp, const void *newp, uptr newlen);
lib/libtsan/sanitizer_common/sanitizer_posix_libcdep.cpp+19
......@@ -47,6 +47,8 @@ typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
4747
4848namespace __sanitizer {
4949
50[[maybe_unused]] static atomic_uint8_t signal_handler_is_from_sanitizer[64];
51
5052u32 GetUid() {
5153 return getuid();
5254}
......@@ -210,6 +212,20 @@ void UnsetAlternateSignalStack() {
210212 UnmapOrDie(oldstack.ss_sp, oldstack.ss_size);
211213}
212214
215bool IsSignalHandlerFromSanitizer(int signum) {
216 return atomic_load(&signal_handler_is_from_sanitizer[signum],
217 memory_order_relaxed);
218}
219
220bool SetSignalHandlerFromSanitizer(int signum, bool new_state) {
221 if (signum < 0 || static_cast<unsigned>(signum) >=
222 ARRAY_SIZE(signal_handler_is_from_sanitizer))
223 return false;
224
225 return atomic_exchange(&signal_handler_is_from_sanitizer[signum], new_state,
226 memory_order_relaxed);
227}
228
213229static void MaybeInstallSigaction(int signum,
214230 SignalHandlerType handler) {
215231 if (GetHandleSignalMode(signum) == kHandleSignalNo) return;
......@@ -223,6 +239,9 @@ static void MaybeInstallSigaction(int signum,
223239 if (common_flags()->use_sigaltstack) sigact.sa_flags |= SA_ONSTACK;
224240 CHECK_EQ(0, internal_sigaction(signum, &sigact, nullptr));
225241 VReport(1, "Installed the sigaction for signal %d\n", signum);
242
243 if (common_flags()->cloak_sanitizer_signal_handlers)
244 SetSignalHandlerFromSanitizer(signum, true);
226245}
227246
228247void InstallDeadlySignalHandlers(SignalHandlerType handler) {
lib/libtsan/sanitizer_common/sanitizer_procmaps_mac.cpp+102-37
......@@ -20,18 +20,21 @@
2020#include <mach/mach.h>
2121
2222// These are not available in older macOS SDKs.
23#ifndef CPU_SUBTYPE_X86_64_H
24#define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t)8) /* Haswell */
25#endif
26#ifndef CPU_SUBTYPE_ARM_V7S
27#define CPU_SUBTYPE_ARM_V7S ((cpu_subtype_t)11) /* Swift */
28#endif
29#ifndef CPU_SUBTYPE_ARM_V7K
30#define CPU_SUBTYPE_ARM_V7K ((cpu_subtype_t)12)
31#endif
32#ifndef CPU_TYPE_ARM64
33#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
34#endif
23# ifndef CPU_SUBTYPE_X86_64_H
24# define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t)8) /* Haswell */
25# endif
26# ifndef CPU_SUBTYPE_ARM_V7S
27# define CPU_SUBTYPE_ARM_V7S ((cpu_subtype_t)11) /* Swift */
28# endif
29# ifndef CPU_SUBTYPE_ARM_V7K
30# define CPU_SUBTYPE_ARM_V7K ((cpu_subtype_t)12)
31# endif
32# ifndef CPU_TYPE_ARM64
33# define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
34# endif
35# ifndef CPU_SUBTYPE_ARM64E
36# define CPU_SUBTYPE_ARM64E ((cpu_subtype_t)2)
37# endif
3538
3639namespace __sanitizer {
3740
......@@ -42,7 +45,6 @@ struct MemoryMappedSegmentData {
4245 const char *current_load_cmd_addr;
4346 u32 lc_type;
4447 uptr base_virt_addr;
45 uptr addr_mask;
4648};
4749
4850template <typename Section>
......@@ -51,12 +53,62 @@ static void NextSectionLoad(LoadedModule *module, MemoryMappedSegmentData *data,
5153 const Section *sc = (const Section *)data->current_load_cmd_addr;
5254 data->current_load_cmd_addr += sizeof(Section);
5355
54 uptr sec_start = (sc->addr & data->addr_mask) + data->base_virt_addr;
56 uptr sec_start = sc->addr + data->base_virt_addr;
5557 uptr sec_end = sec_start + sc->size;
5658 module->addAddressRange(sec_start, sec_end, /*executable=*/false, isWritable,
5759 sc->sectname);
5860}
5961
62static bool VerifyMemoryMapping(MemoryMappingLayout* mapping) {
63 InternalMmapVector<LoadedModule> modules;
64 modules.reserve(128); // matches DumpProcessMap
65 mapping->DumpListOfModules(&modules);
66
67 InternalMmapVector<LoadedModule::AddressRange> segments;
68 for (uptr i = 0; i < modules.size(); ++i) {
69 for (auto& range : modules[i].ranges()) {
70 if (range.beg == range.end)
71 continue;
72 segments.push_back(range);
73 }
74 }
75
76 // Verify that none of the segments overlap:
77 // 1. Sort the segments by the start address
78 // 2. Check that every segment starts after the previous one ends.
79 Sort(segments.data(), segments.size(),
80 [](LoadedModule::AddressRange& a, LoadedModule::AddressRange& b) {
81 return a.beg < b.beg;
82 });
83
84 // To avoid spam, we only print the report message once-per-process.
85 static bool invalid_module_map_reported = false;
86 bool well_formed = true;
87
88 for (size_t i = 1; i < segments.size(); i++) {
89 uptr cur_start = segments[i].beg;
90 uptr prev_end = segments[i - 1].end;
91 if (cur_start < prev_end) {
92 well_formed = false;
93 VReport(2, "Overlapping mappings: %s start = %p, %s end = %p\n",
94 segments[i].name, (void*)cur_start, segments[i - 1].name,
95 (void*)prev_end);
96 if (!invalid_module_map_reported) {
97 Report(
98 "WARN: Invalid dyld module map detected. This is most likely a bug "
99 "in the sanitizer.\n");
100 Report("WARN: Backtraces may be unreliable.\n");
101 invalid_module_map_reported = true;
102 }
103 }
104 }
105
106 for (auto& m : modules) m.clear();
107
108 mapping->Reset();
109 return well_formed;
110}
111
60112void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) {
61113 // Don't iterate over sections when the caller hasn't set up the
62114 // data pointer, when there are no sections, or when the segment
......@@ -82,6 +134,7 @@ void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) {
82134
83135MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
84136 Reset();
137 VerifyMemoryMapping(this);
85138}
86139
87140MemoryMappingLayout::~MemoryMappingLayout() {
......@@ -123,7 +176,7 @@ void MemoryMappingLayout::Reset() {
123176// The dyld load address should be unchanged throughout process execution,
124177// and it is expensive to compute once many libraries have been loaded,
125178// so cache it here and do not reset.
126static mach_header *dyld_hdr = 0;
179static const mach_header* dyld_hdr = 0;
127180static const char kDyldPath[] = "/usr/lib/dyld";
128181static const int kDyldImageIdx = -1;
129182
......@@ -187,17 +240,22 @@ typedef struct dyld_shared_cache_dylib_text_info
187240
188241extern bool _dyld_get_shared_cache_uuid(uuid_t uuid);
189242extern const void *_dyld_get_shared_cache_range(size_t *length);
243extern intptr_t _dyld_get_image_slide(const struct mach_header* mh);
190244extern int dyld_shared_cache_iterate_text(
191245 const uuid_t cacheUuid,
192246 void (^callback)(const dyld_shared_cache_dylib_text_info *info));
247SANITIZER_WEAK_IMPORT const struct mach_header* _dyld_get_dyld_header(void);
193248} // extern "C"
194249
195static mach_header *GetDyldImageHeaderViaSharedCache() {
250static const mach_header* GetDyldImageHeaderViaSharedCache() {
196251 uuid_t uuid;
197252 bool hasCache = _dyld_get_shared_cache_uuid(uuid);
198253 if (!hasCache)
199254 return nullptr;
200255
256 if (&_dyld_get_dyld_header != nullptr)
257 return _dyld_get_dyld_header();
258
201259 size_t cacheLength;
202260 __block uptr cacheStart = (uptr)_dyld_get_shared_cache_range(&cacheLength);
203261 CHECK(cacheStart && cacheLength);
......@@ -255,23 +313,21 @@ static bool NextSegmentLoad(MemoryMappedSegment *segment,
255313 layout_data->current_load_cmd_count--;
256314 if (((const load_command *)lc)->cmd == kLCSegment) {
257315 const SegmentCommand* sc = (const SegmentCommand *)lc;
258 uptr base_virt_addr, addr_mask;
259 if (layout_data->current_image == kDyldImageIdx) {
260 base_virt_addr = (uptr)get_dyld_hdr();
261 // vmaddr is masked with 0xfffff because on macOS versions < 10.12,
262 // it contains an absolute address rather than an offset for dyld.
263 // To make matters even more complicated, this absolute address
264 // isn't actually the absolute segment address, but the offset portion
265 // of the address is accurate when combined with the dyld base address,
266 // and the mask will give just this offset.
267 addr_mask = 0xfffff;
268 } else {
316 if (internal_strcmp(sc->segname, "__LINKEDIT") == 0) {
317 // The LINKEDIT sections are for internal linker use, and may alias
318 // with the LINKEDIT section for other modules. (If we included them,
319 // our memory map would contain overlappping sections.)
320 return false;
321 }
322
323 uptr base_virt_addr;
324 if (layout_data->current_image == kDyldImageIdx)
325 base_virt_addr = (uptr)_dyld_get_image_slide(get_dyld_hdr());
326 else
269327 base_virt_addr =
270328 (uptr)_dyld_get_image_vmaddr_slide(layout_data->current_image);
271 addr_mask = ~0;
272 }
273329
274 segment->start = (sc->vmaddr & addr_mask) + base_virt_addr;
330 segment->start = sc->vmaddr + base_virt_addr;
275331 segment->end = segment->start + sc->vmsize;
276332 // Most callers don't need section information, so only fill this struct
277333 // when required.
......@@ -281,9 +337,9 @@ static bool NextSegmentLoad(MemoryMappedSegment *segment,
281337 (const char *)lc + sizeof(SegmentCommand);
282338 seg_data->lc_type = kLCSegment;
283339 seg_data->base_virt_addr = base_virt_addr;
284 seg_data->addr_mask = addr_mask;
285340 internal_strncpy(seg_data->name, sc->segname,
286341 ARRAY_SIZE(seg_data->name));
342 seg_data->name[ARRAY_SIZE(seg_data->name) - 1] = 0;
287343 }
288344
289345 // Return the initial protection.
......@@ -297,6 +353,7 @@ static bool NextSegmentLoad(MemoryMappedSegment *segment,
297353 ? kDyldPath
298354 : _dyld_get_image_name(layout_data->current_image);
299355 internal_strncpy(segment->filename, src, segment->filename_size);
356 segment->filename[segment->filename_size - 1] = 0;
300357 }
301358 segment->arch = layout_data->current_arch;
302359 internal_memcpy(segment->uuid, layout_data->current_uuid, kModuleUUIDSize);
......@@ -311,18 +368,26 @@ ModuleArch ModuleArchFromCpuType(cpu_type_t cputype, cpu_subtype_t cpusubtype) {
311368 case CPU_TYPE_I386:
312369 return kModuleArchI386;
313370 case CPU_TYPE_X86_64:
314 if (cpusubtype == CPU_SUBTYPE_X86_64_ALL) return kModuleArchX86_64;
315 if (cpusubtype == CPU_SUBTYPE_X86_64_H) return kModuleArchX86_64H;
371 if (cpusubtype == CPU_SUBTYPE_X86_64_ALL)
372 return kModuleArchX86_64;
373 if (cpusubtype == CPU_SUBTYPE_X86_64_H)
374 return kModuleArchX86_64H;
316375 CHECK(0 && "Invalid subtype of x86_64");
317376 return kModuleArchUnknown;
318377 case CPU_TYPE_ARM:
319 if (cpusubtype == CPU_SUBTYPE_ARM_V6) return kModuleArchARMV6;
320 if (cpusubtype == CPU_SUBTYPE_ARM_V7) return kModuleArchARMV7;
321 if (cpusubtype == CPU_SUBTYPE_ARM_V7S) return kModuleArchARMV7S;
322 if (cpusubtype == CPU_SUBTYPE_ARM_V7K) return kModuleArchARMV7K;
378 if (cpusubtype == CPU_SUBTYPE_ARM_V6)
379 return kModuleArchARMV6;
380 if (cpusubtype == CPU_SUBTYPE_ARM_V7)
381 return kModuleArchARMV7;
382 if (cpusubtype == CPU_SUBTYPE_ARM_V7S)
383 return kModuleArchARMV7S;
384 if (cpusubtype == CPU_SUBTYPE_ARM_V7K)
385 return kModuleArchARMV7K;
323386 CHECK(0 && "Invalid subtype of ARM");
324387 return kModuleArchUnknown;
325388 case CPU_TYPE_ARM64:
389 if (cpusubtype == CPU_SUBTYPE_ARM64E)
390 return kModuleArchARM64E;
326391 return kModuleArchARM64;
327392 default:
328393 CHECK(0 && "Invalid CPU type");
lib/libtsan/sanitizer_common/sanitizer_redefine_builtins.h+1-1
......@@ -15,7 +15,7 @@
1515# define SANITIZER_REDEFINE_BUILTINS_H
1616
1717// The asm hack only works with GCC and Clang.
18# if !defined(_WIN32) && !defined(_AIX)
18# if !defined(_WIN32) && !defined(_AIX) && !defined(__APPLE__)
1919
2020asm(R"(
2121 .set memcpy, __sanitizer_internal_memcpy
lib/libtsan/sanitizer_common/sanitizer_signal_interceptors.inc+40-2
......@@ -45,6 +45,8 @@ using namespace __sanitizer;
4545INTERCEPTOR(uptr, bsd_signal, int signum, uptr handler) {
4646 SIGNAL_INTERCEPTOR_ENTER();
4747 if (GetHandleSignalMode(signum) == kHandleSignalExclusive) return 0;
48
49 // TODO: support cloak_sanitizer_signal_handlers
4850 SIGNAL_INTERCEPTOR_SIGNAL_IMPL(bsd_signal, signum, handler);
4951}
5052#define INIT_BSD_SIGNAL COMMON_INTERCEPT_FUNCTION(bsd_signal)
......@@ -56,19 +58,55 @@ INTERCEPTOR(uptr, bsd_signal, int signum, uptr handler) {
5658INTERCEPTOR(uptr, signal, int signum, uptr handler) {
5759 SIGNAL_INTERCEPTOR_ENTER();
5860 if (GetHandleSignalMode(signum) == kHandleSignalExclusive)
61 // The user can neither view nor change the signal handler, regardless of
62 // the cloak_sanitizer_signal_handlers setting. This differs from
63 // sigaction().
5964 return (uptr) nullptr;
60 SIGNAL_INTERCEPTOR_SIGNAL_IMPL(signal, signum, handler);
65
66 uptr ret = +[](auto signal, int signum, uptr handler) {
67 SIGNAL_INTERCEPTOR_SIGNAL_IMPL(signal, signum, handler);
68 }(signal, signum, handler);
69
70 if (ret != sig_err && SetSignalHandlerFromSanitizer(signum, false))
71 // If the user sets a signal handler, it becomes uncloaked, even if they
72 // reuse a sanitizer's signal handler.
73 ret = sig_dfl;
74
75 return ret;
6176}
6277#define INIT_SIGNAL COMMON_INTERCEPT_FUNCTION(signal)
6378
6479INTERCEPTOR(int, sigaction_symname, int signum,
6580 const __sanitizer_sigaction *act, __sanitizer_sigaction *oldact) {
6681 SIGNAL_INTERCEPTOR_ENTER();
82
6783 if (GetHandleSignalMode(signum) == kHandleSignalExclusive) {
6884 if (!oldact) return 0;
6985 act = nullptr;
86 // If cloak_sanitizer_signal_handlers=true, the user can neither view nor
87 // change the signal handle.
88 // If false, the user can view but not change the signal handler. This
89 // differs from signal().
7090 }
71 SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signum, act, oldact);
91
92 int ret = +[](int signum, const __sanitizer_sigaction* act,
93 __sanitizer_sigaction* oldact) {
94 SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signum, act, oldact);
95 }(signum, act, oldact);
96
97 if (act) {
98 if (ret == 0 && SetSignalHandlerFromSanitizer(signum, false)) {
99 // If the user sets a signal handler, it becomes uncloaked, even if they
100 // reuse a sanitizer's signal handler.
101
102 if (oldact)
103 oldact->handler = reinterpret_cast<__sanitizer_sighandler_ptr>(sig_dfl);
104 }
105 } else if (ret == 0 && oldact && IsSignalHandlerFromSanitizer(signum)) {
106 oldact->handler = reinterpret_cast<__sanitizer_sighandler_ptr>(sig_dfl);
107 }
108
109 return ret;
72110}
73111#define INIT_SIGACTION COMMON_INTERCEPT_FUNCTION(sigaction_symname)
74112
lib/libtsan/sanitizer_common/sanitizer_stoptheworld.h+1-1
......@@ -38,7 +38,7 @@ class SuspendedThreadsList {
3838 }
3939
4040 virtual uptr ThreadCount() const { UNIMPLEMENTED(); }
41 virtual tid_t GetThreadID(uptr index) const { UNIMPLEMENTED(); }
41 virtual ThreadID GetThreadID(uptr index) const { UNIMPLEMENTED(); }
4242
4343 protected:
4444 ~SuspendedThreadsList() {}
lib/libtsan/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp+83-12
......@@ -94,17 +94,17 @@ class SuspendedThreadsListLinux final : public SuspendedThreadsList {
9494 public:
9595 SuspendedThreadsListLinux() { thread_ids_.reserve(1024); }
9696
97 tid_t GetThreadID(uptr index) const override;
97 ThreadID GetThreadID(uptr index) const override;
9898 uptr ThreadCount() const override;
99 bool ContainsTid(tid_t thread_id) const;
100 void Append(tid_t tid);
99 bool ContainsTid(ThreadID thread_id) const;
100 void Append(ThreadID tid);
101101
102102 PtraceRegistersStatus GetRegistersAndSP(uptr index,
103103 InternalMmapVector<uptr> *buffer,
104104 uptr *sp) const override;
105105
106106 private:
107 InternalMmapVector<tid_t> thread_ids_;
107 InternalMmapVector<ThreadID> thread_ids_;
108108};
109109
110110// Structure for passing arguments into the tracer thread.
......@@ -137,10 +137,10 @@ class ThreadSuspender {
137137 private:
138138 SuspendedThreadsListLinux suspended_threads_list_;
139139 pid_t pid_;
140 bool SuspendThread(tid_t thread_id);
140 bool SuspendThread(ThreadID thread_id);
141141};
142142
143bool ThreadSuspender::SuspendThread(tid_t tid) {
143bool ThreadSuspender::SuspendThread(ThreadID tid) {
144144 int pterrno;
145145 if (internal_iserror(internal_ptrace(PTRACE_ATTACH, tid, nullptr, nullptr),
146146 &pterrno)) {
......@@ -210,7 +210,7 @@ void ThreadSuspender::KillAllThreads() {
210210bool ThreadSuspender::SuspendAllThreads() {
211211 ThreadLister thread_lister(pid_);
212212 bool retry = true;
213 InternalMmapVector<tid_t> threads;
213 InternalMmapVector<ThreadID> threads;
214214 threads.reserve(128);
215215 for (int i = 0; i < 30 && retry; ++i) {
216216 retry = false;
......@@ -226,7 +226,7 @@ bool ThreadSuspender::SuspendAllThreads() {
226226 case ThreadLister::Ok:
227227 break;
228228 }
229 for (tid_t tid : threads) {
229 for (ThreadID tid : threads) {
230230 // Are we already attached to this thread?
231231 // Currently this check takes linear time, however the number of threads
232232 // is usually small.
......@@ -403,7 +403,77 @@ struct ScopedSetTracerPID {
403403 }
404404};
405405
406// This detects whether ptrace is blocked (e.g., by seccomp), by forking and
407// then attempting ptrace.
408// This separate check is necessary because StopTheWorld() creates a thread
409// with a shared virtual address space and shared TLS, and therefore
410// cannot use waitpid() due to the shared errno.
411static void TestPTrace() {
412# if SANITIZER_SPARC
413 // internal_fork() on SPARC actually calls __fork(). We can't safely fork,
414 // because it's possible seccomp has been configured to disallow fork() but
415 // allow clone().
416 VReport(1, "WARNING: skipping TestPTrace() because this is SPARC\n");
417 VReport(1,
418 "If seccomp blocks ptrace, LeakSanitizer may hang without further "
419 "notice\n");
420 VReport(
421 1,
422 "If seccomp does not block ptrace, you can safely ignore this warning\n");
423# else
424 // Heuristic: only check the first time this is called. This is not always
425 // correct (e.g., user manually triggers leak detection, then updates
426 // seccomp, then leak detection is triggered again).
427 static bool checked = false;
428 if (checked)
429 return;
430 checked = true;
431
432 // Hopefully internal_fork() is not too expensive, thanks to copy-on-write.
433 // Besides, this is only called the first time.
434 // Note that internal_fork() on non-SPARC Linux actually calls
435 // SYSCALL(clone); thus, it is reasonable to use it because if seccomp kills
436 // TestPTrace(), it would have killed StopTheWorld() anyway.
437 int pid = internal_fork();
438
439 if (pid < 0) {
440 int rverrno;
441 if (internal_iserror(pid, &rverrno))
442 VReport(0, "WARNING: TestPTrace() failed to fork (errno %d)\n", rverrno);
443
444 // We don't abort the sanitizer - it's still worth letting the sanitizer
445 // try.
446 return;
447 }
448
449 if (pid == 0) {
450 // Child subprocess
451
452 // TODO: consider checking return value of internal_ptrace, to handle
453 // SCMP_ACT_ERRNO. However, be careful not to consume too many
454 // resources performing a proper ptrace.
455 internal_ptrace(PTRACE_ATTACH, 0, nullptr, nullptr);
456 internal__exit(0);
457 } else {
458 int wstatus;
459 internal_waitpid(pid, &wstatus, 0);
460
461 // Handle SCMP_ACT_KILL
462 if (WIFSIGNALED(wstatus)) {
463 VReport(0,
464 "WARNING: ptrace appears to be blocked (is seccomp enabled?). "
465 "LeakSanitizer may hang.\n");
466 VReport(0, "Child exited with signal %d.\n", WTERMSIG(wstatus));
467 // We don't abort the sanitizer - it's still worth letting the sanitizer
468 // try.
469 }
470 }
471# endif
472}
473
406474void StopTheWorld(StopTheWorldCallback callback, void *argument) {
475 TestPTrace();
476
407477 StopTheWorldScope in_stoptheworld;
408478 // Prepare the arguments for TracerThread.
409479 struct TracerThreadArgument tracer_thread_argument;
......@@ -457,7 +527,8 @@ void StopTheWorld(StopTheWorldCallback callback, void *argument) {
457527 internal_prctl(PR_SET_PTRACER, tracer_pid, 0, 0, 0);
458528 // Allow the tracer thread to start.
459529 tracer_thread_argument.mutex.Unlock();
460 // NOTE: errno is shared between this thread and the tracer thread.
530 // NOTE: errno is shared between this thread and the tracer thread
531 // (clone was called without CLONE_SETTLS / newtls).
461532 // internal_waitpid() may call syscall() which can access/spoil errno,
462533 // so we can't call it now. Instead we for the tracer thread to finish using
463534 // the spin loop below. Man page for sched_yield() says "In the Linux
......@@ -546,7 +617,7 @@ static constexpr uptr kExtraRegs[] = {0};
546617#error "Unsupported architecture"
547618#endif // SANITIZER_ANDROID && defined(__arm__)
548619
549tid_t SuspendedThreadsListLinux::GetThreadID(uptr index) const {
620ThreadID SuspendedThreadsListLinux::GetThreadID(uptr index) const {
550621 CHECK_LT(index, thread_ids_.size());
551622 return thread_ids_[index];
552623}
......@@ -555,14 +626,14 @@ uptr SuspendedThreadsListLinux::ThreadCount() const {
555626 return thread_ids_.size();
556627}
557628
558bool SuspendedThreadsListLinux::ContainsTid(tid_t thread_id) const {
629bool SuspendedThreadsListLinux::ContainsTid(ThreadID thread_id) const {
559630 for (uptr i = 0; i < thread_ids_.size(); i++) {
560631 if (thread_ids_[i] == thread_id) return true;
561632 }
562633 return false;
563634}
564635
565void SuspendedThreadsListLinux::Append(tid_t tid) {
636void SuspendedThreadsListLinux::Append(ThreadID tid) {
566637 thread_ids_.push_back(tid);
567638}
568639
lib/libtsan/sanitizer_common/sanitizer_stoptheworld_mac.cpp+3-3
......@@ -23,7 +23,7 @@
2323
2424namespace __sanitizer {
2525typedef struct {
26 tid_t tid;
26 ThreadID tid;
2727 thread_t thread;
2828} SuspendedThreadInfo;
2929
......@@ -31,7 +31,7 @@ class SuspendedThreadsListMac final : public SuspendedThreadsList {
3131 public:
3232 SuspendedThreadsListMac() = default;
3333
34 tid_t GetThreadID(uptr index) const override;
34 ThreadID GetThreadID(uptr index) const override;
3535 thread_t GetThread(uptr index) const;
3636 uptr ThreadCount() const override;
3737 bool ContainsThread(thread_t thread) const;
......@@ -111,7 +111,7 @@ typedef x86_thread_state32_t regs_struct;
111111#error "Unsupported architecture"
112112#endif
113113
114tid_t SuspendedThreadsListMac::GetThreadID(uptr index) const {
114ThreadID SuspendedThreadsListMac::GetThreadID(uptr index) const {
115115 CHECK_LT(index, threads_.size());
116116 return threads_[index].tid;
117117}
lib/libtsan/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp+7-7
......@@ -52,17 +52,17 @@ class SuspendedThreadsListNetBSD final : public SuspendedThreadsList {
5252 public:
5353 SuspendedThreadsListNetBSD() { thread_ids_.reserve(1024); }
5454
55 tid_t GetThreadID(uptr index) const;
55 ThreadID GetThreadID(uptr index) const;
5656 uptr ThreadCount() const;
57 bool ContainsTid(tid_t thread_id) const;
58 void Append(tid_t tid);
57 bool ContainsTid(ThreadID thread_id) const;
58 void Append(ThreadID tid);
5959
6060 PtraceRegistersStatus GetRegistersAndSP(uptr index,
6161 InternalMmapVector<uptr> *buffer,
6262 uptr *sp) const;
6363
6464 private:
65 InternalMmapVector<tid_t> thread_ids_;
65 InternalMmapVector<ThreadID> thread_ids_;
6666};
6767
6868struct TracerThreadArgument {
......@@ -313,7 +313,7 @@ void StopTheWorld(StopTheWorldCallback callback, void *argument) {
313313 }
314314}
315315
316tid_t SuspendedThreadsListNetBSD::GetThreadID(uptr index) const {
316ThreadID SuspendedThreadsListNetBSD::GetThreadID(uptr index) const {
317317 CHECK_LT(index, thread_ids_.size());
318318 return thread_ids_[index];
319319}
......@@ -322,7 +322,7 @@ uptr SuspendedThreadsListNetBSD::ThreadCount() const {
322322 return thread_ids_.size();
323323}
324324
325bool SuspendedThreadsListNetBSD::ContainsTid(tid_t thread_id) const {
325bool SuspendedThreadsListNetBSD::ContainsTid(ThreadID thread_id) const {
326326 for (uptr i = 0; i < thread_ids_.size(); i++) {
327327 if (thread_ids_[i] == thread_id)
328328 return true;
......@@ -330,7 +330,7 @@ bool SuspendedThreadsListNetBSD::ContainsTid(tid_t thread_id) const {
330330 return false;
331331}
332332
333void SuspendedThreadsListNetBSD::Append(tid_t tid) {
333void SuspendedThreadsListNetBSD::Append(ThreadID tid) {
334334 thread_ids_.push_back(tid);
335335}
336336
lib/libtsan/sanitizer_common/sanitizer_stoptheworld_win.cpp+2-2
......@@ -38,7 +38,7 @@ struct SuspendedThreadsListWindows final : public SuspendedThreadsList {
3838 InternalMmapVector<uptr> *buffer,
3939 uptr *sp) const override;
4040
41 tid_t GetThreadID(uptr index) const override;
41 ThreadID GetThreadID(uptr index) const override;
4242 uptr ThreadCount() const override;
4343};
4444
......@@ -68,7 +68,7 @@ PtraceRegistersStatus SuspendedThreadsListWindows::GetRegistersAndSP(
6868 return REGISTERS_AVAILABLE;
6969}
7070
71tid_t SuspendedThreadsListWindows::GetThreadID(uptr index) const {
71ThreadID SuspendedThreadsListWindows::GetThreadID(uptr index) const {
7272 CHECK_LT(index, threadIds.size());
7373 return threadIds[index];
7474}
lib/libtsan/sanitizer_common/sanitizer_symbolizer_internal.h+5-1
......@@ -83,7 +83,7 @@ class SymbolizerProcess {
8383 const char *SendCommand(const char *command);
8484
8585 protected:
86 ~SymbolizerProcess() {}
86 ~SymbolizerProcess();
8787
8888 /// The maximum number of arguments required to invoke a tool process.
8989 static const unsigned kArgVMax = 16;
......@@ -114,6 +114,10 @@ class SymbolizerProcess {
114114 fd_t input_fd_;
115115 fd_t output_fd_;
116116
117 // We hold on to the child's stdin fd (the read end of the pipe)
118 // so that when we write to it, we don't get a SIGPIPE
119 fd_t child_stdin_fd_;
120
117121 InternalMmapVector<char> buffer_;
118122
119123 static const uptr kMaxTimesRestarted = 5;
lib/libtsan/sanitizer_common/sanitizer_symbolizer_libcdep.cpp+11-1
......@@ -476,10 +476,11 @@ const char *LLVMSymbolizer::FormatAndSendCommand(const char *command_prefix,
476476 return symbolizer_process_->SendCommand(buffer_);
477477}
478478
479SymbolizerProcess::SymbolizerProcess(const char *path, bool use_posix_spawn)
479SymbolizerProcess::SymbolizerProcess(const char* path, bool use_posix_spawn)
480480 : path_(path),
481481 input_fd_(kInvalidFd),
482482 output_fd_(kInvalidFd),
483 child_stdin_fd_(kInvalidFd),
483484 times_restarted_(0),
484485 failed_to_start_(false),
485486 reported_invalid_path_(false),
......@@ -488,6 +489,11 @@ SymbolizerProcess::SymbolizerProcess(const char *path, bool use_posix_spawn)
488489 CHECK_NE(path_[0], '\0');
489490}
490491
492SymbolizerProcess::~SymbolizerProcess() {
493 if (child_stdin_fd_ != kInvalidFd)
494 CloseFile(child_stdin_fd_);
495}
496
491497static bool IsSameModule(const char *path) {
492498 if (const char *ProcessName = GetProcessName()) {
493499 if (const char *SymbolizerName = StripModuleName(path)) {
......@@ -533,6 +539,10 @@ bool SymbolizerProcess::Restart() {
533539 CloseFile(input_fd_);
534540 if (output_fd_ != kInvalidFd)
535541 CloseFile(output_fd_);
542 if (child_stdin_fd_ != kInvalidFd) {
543 CloseFile(child_stdin_fd_);
544 child_stdin_fd_ = kInvalidFd; // Don't free in destructor
545 }
536546 return StartSymbolizerSubprocess();
537547}
538548
lib/libtsan/sanitizer_common/sanitizer_symbolizer_mac.cpp+86-29
......@@ -78,13 +78,25 @@ class AtosSymbolizerProcess final : public SymbolizerProcess {
7878 }
7979
8080 bool ReachedEndOfOutput(const char *buffer, uptr length) const override {
81 return (length >= 1 && buffer[length - 1] == '\n');
81 if (common_flags()->symbolize_inline_frames) {
82 // When running with -i, atos sends two newlines at the end of each
83 // address it symbolizes. This indicates the end of the set of frames
84 // for a particular address.
85 return length >= 2 && buffer[length - 1] == '\n' &&
86 buffer[length - 2] == '\n';
87 } else {
88 // When running without -i, atos only sends a single newline at
89 // the end of each address it symbolizes.
90 return length >= 1 && buffer[length - 1] == '\n';
91 }
8292 }
8393
8494 void GetArgV(const char *path_to_binary,
8595 const char *(&argv)[kArgVMax]) const override {
8696 int i = 0;
8797 argv[i++] = path_to_binary;
98 if (common_flags()->symbolize_inline_frames)
99 argv[i++] = "-i";
88100 argv[i++] = "-p";
89101 argv[i++] = &pid_str_[0];
90102 if (GetMacosAlignedVersion() == MacosVersion(10, 9)) {
......@@ -102,12 +114,16 @@ class AtosSymbolizerProcess final : public SymbolizerProcess {
102114
103115#undef K_ATOS_ENV_VAR
104116
105static bool ParseCommandOutput(const char *str, uptr addr, char **out_name,
106 char **out_module, char **out_file, uptr *line,
107 uptr *start_address) {
117// Parses a single frame (one line) from str, and returns the pointer to the
118// next character to parse (i.e. after the newline) if successful. If
119// it fails, returns NULL.
120static const char* ParseCommandOutput(const char* str, uptr addr,
121 char** out_name, char** out_module,
122 char** out_file, uptr* line,
123 uptr* start_address) {
108124 // Trim ending newlines.
109125 char *trim;
110 ExtractTokenUpToDelimiter(str, "\n", &trim);
126 str = ExtractTokenUpToDelimiter(str, "\n", &trim);
111127
112128 // The line from `atos` is in one of these formats:
113129 // myfunction (in library.dylib) (sourcefile.c:17)
......@@ -124,7 +140,7 @@ static bool ParseCommandOutput(const char *str, uptr addr, char **out_name,
124140 if (rest[0] == '\0') {
125141 InternalFree(symbol_name);
126142 InternalFree(trim);
127 return false;
143 return NULL;
128144 }
129145
130146 if (internal_strncmp(symbol_name, "0x", 2) != 0)
......@@ -149,7 +165,7 @@ static bool ParseCommandOutput(const char *str, uptr addr, char **out_name,
149165 }
150166
151167 InternalFree(trim);
152 return true;
168 return str;
153169}
154170
155171AtosSymbolizer::AtosSymbolizer(const char *path, LowLevelAllocator *allocator)
......@@ -161,31 +177,72 @@ bool AtosSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
161177 char command[32];
162178 internal_snprintf(command, sizeof(command), "0x%zx\n", addr);
163179 const char *buf = process_->SendCommand(command);
164 if (!buf) return false;
165 uptr line;
166 uptr start_address = AddressInfo::kUnknown;
167 if (!ParseCommandOutput(buf, addr, &stack->info.function, &stack->info.module,
168 &stack->info.file, &line, &start_address)) {
169 Report("WARNING: atos failed to symbolize address \"0x%zx\"\n", addr);
180 if (!buf)
170181 return false;
171 }
172 stack->info.line = (int)line;
173
174 if (start_address == AddressInfo::kUnknown) {
175 // Fallback to dladdr() to get function start address if atos doesn't report
176 // it.
177 Dl_info info;
178 int result = dladdr((const void *)addr, &info);
179 if (result)
180 start_address = reinterpret_cast<uptr>(info.dli_saddr);
181 }
182182
183 // Only assign to `function_offset` if we were able to get the function's
184 // start address and we got a sensible `start_address` (dladdr doesn't always
185 // ensure that `addr >= sym_addr`).
186 if (start_address != AddressInfo::kUnknown && addr >= start_address) {
187 stack->info.function_offset = addr - start_address;
183 SymbolizedStack* last = stack;
184 bool top_frame = true;
185
186 // Parse one line of input (i.e. one frame).
187 //
188 // When symbolize_inline_frames=true, an empty line
189 // (i.e. \n at the beginning of a line) indicates that the last
190 // frame has been sent.
191 //
192 // When symbolize_inline_frames=false, the symbolizer will send only
193 // one frame (without a empty line), so loop runs exactly once
194 // and hits an early `break`.
195 while (*buf != '\n') {
196 uptr line;
197 uptr start_address = AddressInfo::kUnknown;
198
199 SymbolizedStack* cur;
200 if (top_frame) {
201 cur = stack;
202 } else {
203 cur = SymbolizedStack::New(stack->info.address);
204 cur->info.FillModuleInfo(stack->info.module, stack->info.module_offset,
205 stack->info.module_arch);
206 last->next = cur;
207 last = cur;
208 }
209
210 // Parse one line of input (i.e. one frame)
211 // If this succeeds, buf will be updated to point to the first character
212 // after the newline.
213 buf = ParseCommandOutput(buf, addr, &cur->info.function, &cur->info.module,
214 &cur->info.file, &line, &start_address);
215
216 // Upon failure, ParseCommandOutput returns NULL.
217 if (!buf) {
218 Report("WARNING: atos failed to symbolize address \"0x%zx\"\n", addr);
219 return false;
220 }
221 cur->info.line = (int)line;
222
223 if (top_frame && start_address == AddressInfo::kUnknown) {
224 // Fallback to dladdr() to get function start address if atos doesn't
225 // report it.
226 Dl_info info;
227 int result = dladdr((const void*)addr, &info);
228 if (result)
229 start_address = reinterpret_cast<uptr>(info.dli_saddr);
230 }
231
232 // Only assign to `function_offset` if we were able to get the function's
233 // start address and we got a sensible `start_address` (dladdr doesn't
234 // always ensure that `addr >= sym_addr`).
235 if (start_address != AddressInfo::kUnknown && addr >= start_address) {
236 cur->info.function_offset = addr - start_address;
237 }
238
239 // atos only sends one line when inline frames are off
240 if (!common_flags()->symbolize_inline_frames)
241 break;
242
243 top_frame = false;
188244 }
245
189246 return true;
190247}
191248
lib/libtsan/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp+27-16
......@@ -156,30 +156,34 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
156156 Printf("\n");
157157 }
158158
159 fd_t infd[2] = {}, outfd[2] = {};
160 if (!CreateTwoHighNumberedPipes(infd, outfd)) {
161 Report(
162 "WARNING: Can't create a socket pair to start "
163 "external symbolizer (errno: %d)\n",
164 errno);
165 return false;
166 }
167
159168 if (use_posix_spawn_) {
160169# if SANITIZER_APPLE
161 fd_t fd = internal_spawn(argv, const_cast<const char **>(GetEnvP()), &pid);
162 if (fd == kInvalidFd) {
170 bool success = internal_spawn(argv, const_cast<const char**>(GetEnvP()),
171 &pid, outfd[0], infd[1]);
172 if (!success) {
163173 Report("WARNING: failed to spawn external symbolizer (errno: %d)\n",
164174 errno);
175 internal_close(infd[0]);
176 internal_close(outfd[1]);
165177 return false;
166178 }
167179
168 input_fd_ = fd;
169 output_fd_ = fd;
180 // We intentionally hold on to the read-end so that we don't get a SIGPIPE
181 child_stdin_fd_ = outfd[0];
182
170183# else // SANITIZER_APPLE
171184 UNIMPLEMENTED();
172185# endif // SANITIZER_APPLE
173186 } else {
174 fd_t infd[2] = {}, outfd[2] = {};
175 if (!CreateTwoHighNumberedPipes(infd, outfd)) {
176 Report(
177 "WARNING: Can't create a socket pair to start "
178 "external symbolizer (errno: %d)\n",
179 errno);
180 return false;
181 }
182
183187 pid = StartSubprocess(path_, argv, GetEnvP(), /* stdin */ outfd[0],
184188 /* stdout */ infd[1]);
185189 if (pid < 0) {
......@@ -187,11 +191,11 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
187191 internal_close(outfd[1]);
188192 return false;
189193 }
190
191 input_fd_ = infd[0];
192 output_fd_ = outfd[1];
193194 }
194195
196 input_fd_ = infd[0];
197 output_fd_ = outfd[1];
198
195199 CHECK_GT(pid, 0);
196200
197201 // Check that symbolizer subprocess started successfully.
......@@ -505,6 +509,13 @@ static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,
505509 }
506510
507511# if SANITIZER_APPLE
512 if (list->empty()) {
513 Report(
514 "WARN: No external symbolizers found. Symbols may be missing or "
515 "unreliable.\n");
516 Report(
517 "HINT: Is PATH set? Does sandbox allow file-read of /usr/bin/atos?\n");
518 }
508519 VReport(2, "Using dladdr symbolizer.\n");
509520 list->push_back(new (*allocator) DlAddrSymbolizer());
510521# endif // SANITIZER_APPLE
lib/libtsan/sanitizer_common/sanitizer_thread_registry.cpp+5-4
......@@ -80,7 +80,7 @@ void ThreadContextBase::SetFinished() {
8080 OnFinished();
8181}
8282
83void ThreadContextBase::SetStarted(tid_t _os_id, ThreadType _thread_type,
83void ThreadContextBase::SetStarted(ThreadID _os_id, ThreadType _thread_type,
8484 void *arg) {
8585 status = ThreadStatusRunning;
8686 os_id = _os_id;
......@@ -228,7 +228,8 @@ static bool FindThreadContextByOsIdCallback(ThreadContextBase *tctx,
228228 tctx->status != ThreadStatusDead);
229229}
230230
231ThreadContextBase *ThreadRegistry::FindThreadContextByOsIDLocked(tid_t os_id) {
231ThreadContextBase *ThreadRegistry::FindThreadContextByOsIDLocked(
232 ThreadID os_id) {
232233 return FindThreadContextLocked(FindThreadContextByOsIdCallback,
233234 (void *)os_id);
234235}
......@@ -322,8 +323,8 @@ ThreadStatus ThreadRegistry::FinishThread(u32 tid) {
322323 return prev_status;
323324}
324325
325void ThreadRegistry::StartThread(u32 tid, tid_t os_id, ThreadType thread_type,
326 void *arg) {
326void ThreadRegistry::StartThread(u32 tid, ThreadID os_id,
327 ThreadType thread_type, void *arg) {
327328 ThreadRegistryLock l(this);
328329 running_threads_++;
329330 ThreadContextBase *tctx = threads_[tid];
lib/libtsan/sanitizer_common/sanitizer_thread_registry.h+4-4
......@@ -43,7 +43,7 @@ class ThreadContextBase {
4343 const u32 tid; // Thread ID. Main thread should have tid = 0.
4444 u64 unique_id; // Unique thread ID.
4545 u32 reuse_count; // Number of times this tid was reused.
46 tid_t os_id; // PID (used for reporting).
46 ThreadID os_id; // PID (used for reporting).
4747 uptr user_id; // Some opaque user thread id (e.g. pthread_t).
4848 char name[64]; // As annotated by user.
4949
......@@ -62,7 +62,7 @@ class ThreadContextBase {
6262 void SetDead();
6363 void SetJoined(void *arg);
6464 void SetFinished();
65 void SetStarted(tid_t _os_id, ThreadType _thread_type, void *arg);
65 void SetStarted(ThreadID _os_id, ThreadType _thread_type, void *arg);
6666 void SetCreated(uptr _user_id, u64 _unique_id, bool _detached,
6767 u32 _parent_tid, u32 _stack_tid, void *arg);
6868 void Reset();
......@@ -126,7 +126,7 @@ class SANITIZER_MUTEX ThreadRegistry {
126126 // is found.
127127 ThreadContextBase *FindThreadContextLocked(FindThreadCallback cb,
128128 void *arg);
129 ThreadContextBase *FindThreadContextByOsIDLocked(tid_t os_id);
129 ThreadContextBase *FindThreadContextByOsIDLocked(ThreadID os_id);
130130
131131 void SetThreadName(u32 tid, const char *name);
132132 void SetThreadNameByUserId(uptr user_id, const char *name);
......@@ -134,7 +134,7 @@ class SANITIZER_MUTEX ThreadRegistry {
134134 void JoinThread(u32 tid, void *arg);
135135 // Finishes thread and returns previous status.
136136 ThreadStatus FinishThread(u32 tid);
137 void StartThread(u32 tid, tid_t os_id, ThreadType thread_type, void *arg);
137 void StartThread(u32 tid, ThreadID os_id, ThreadType thread_type, void *arg);
138138 u32 ConsumeThreadUserId(uptr user_id);
139139 void SetThreadUserId(u32 tid, uptr user_id);
140140
lib/libtsan/sanitizer_common/sanitizer_win.cpp+1-3
......@@ -108,9 +108,7 @@ int internal_dlinfo(void *handle, int request, void *p) {
108108
109109// In contrast to POSIX, on Windows GetCurrentThreadId()
110110// returns a system-unique identifier.
111tid_t GetTid() {
112 return GetCurrentThreadId();
113}
111ThreadID GetTid() { return GetCurrentThreadId(); }
114112
115113uptr GetThreadSelf() {
116114 return GetTid();
lib/libtsan/tsan_debugging.cpp+2-2
......@@ -165,7 +165,7 @@ int __tsan_get_report_mutex(void *report, uptr idx, uptr *mutex_id, void **addr,
165165}
166166
167167SANITIZER_INTERFACE_ATTRIBUTE
168int __tsan_get_report_thread(void *report, uptr idx, int *tid, tid_t *os_id,
168int __tsan_get_report_thread(void *report, uptr idx, int *tid, ThreadID *os_id,
169169 int *running, const char **name, int *parent_tid,
170170 void **trace, uptr trace_size) {
171171 const ReportDesc *rep = (ReportDesc *)report;
......@@ -242,7 +242,7 @@ const char *__tsan_locate_address(uptr addr, char *name, uptr name_size,
242242
243243SANITIZER_INTERFACE_ATTRIBUTE
244244int __tsan_get_alloc_stack(uptr addr, uptr *trace, uptr size, int *thread_id,
245 tid_t *os_id) {
245 ThreadID *os_id) {
246246 MBlock *b = 0;
247247 Allocator *a = allocator();
248248 if (a->PointerIsMine((void *)addr)) {
lib/libtsan/tsan_flags.cpp+37
......@@ -20,6 +20,43 @@
2020#include "tsan_rtl.h"
2121#include "ubsan/ubsan_flags.h"
2222
23#if SANITIZER_APPLE && !SANITIZER_GO
24namespace __sanitizer {
25
26template <>
27inline bool FlagHandler<LockDuringWriteSetting>::Parse(const char *value) {
28 if (internal_strcmp(value, "on") == 0) {
29 *t_ = kLockDuringAllWrites;
30 return true;
31 }
32 if (internal_strcmp(value, "disable_for_current_process") == 0) {
33 *t_ = kNoLockDuringWritesCurrentProcess;
34 return true;
35 }
36 if (internal_strcmp(value, "disable_for_all_processes") == 0) {
37 *t_ = kNoLockDuringWritesAllProcesses;
38 return true;
39 }
40 Printf("ERROR: Invalid value for signal handler option: '%s'\n", value);
41 return false;
42}
43
44template <>
45inline bool FlagHandler<LockDuringWriteSetting>::Format(char *buffer,
46 uptr size) {
47 switch (*t_) {
48 case kLockDuringAllWrites:
49 return FormatString(buffer, size, "on");
50 case kNoLockDuringWritesCurrentProcess:
51 return FormatString(buffer, size, "disable_for_current_process");
52 case kNoLockDuringWritesAllProcesses:
53 return FormatString(buffer, size, "disable_for_all_processes");
54 }
55}
56
57} // namespace __sanitizer
58#endif // SANITIZER_APPLE && !SANITIZER_GO
59
2360namespace __tsan {
2461
2562// Can be overriden in frontend.
lib/libtsan/tsan_flags.h+8
......@@ -16,6 +16,14 @@
1616#include "sanitizer_common/sanitizer_flags.h"
1717#include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
1818
19#if SANITIZER_APPLE && !SANITIZER_GO
20enum LockDuringWriteSetting {
21 kLockDuringAllWrites,
22 kNoLockDuringWritesCurrentProcess,
23 kNoLockDuringWritesAllProcesses,
24};
25#endif
26
1927namespace __tsan {
2028
2129struct Flags : DDFlags {
lib/libtsan/tsan_flags.inc+12
......@@ -80,3 +80,15 @@ TSAN_FLAG(bool, shared_ptr_interceptor, true,
8080TSAN_FLAG(bool, print_full_thread_history, false,
8181 "If set, prints thread creation stacks for the threads involved in "
8282 "the report and their ancestors up to the main thread.")
83
84#if SANITIZER_APPLE && !SANITIZER_GO
85TSAN_FLAG(LockDuringWriteSetting, lock_during_write, kLockDuringAllWrites,
86 "Determines whether to obtain a lock while writing logs or error "
87 "reports. "
88 "\"on\" - [default] lock during all writes. "
89 "\"disable_for_current_process\" - don't lock during all writes in "
90 "the current process, but do lock for all writes in child "
91 "processes."
92 "\"disable_for_all_processes\" - don't lock during all writes in "
93 "the current process and it's children processes.")
94#endif
lib/libtsan/tsan_interceptors.h+9-1
......@@ -1,6 +1,9 @@
11#ifndef TSAN_INTERCEPTORS_H
22#define TSAN_INTERCEPTORS_H
33
4#if SANITIZER_APPLE && !SANITIZER_GO
5# include "sanitizer_common/sanitizer_mac.h"
6#endif
47#include "sanitizer_common/sanitizer_stacktrace.h"
58#include "tsan_rtl.h"
69
......@@ -43,7 +46,12 @@ inline bool in_symbolizer() {
4346#endif
4447
4548inline bool MustIgnoreInterceptor(ThreadState *thr) {
46 return !thr->is_inited || thr->ignore_interceptors || thr->in_ignored_lib;
49 return !thr->is_inited || thr->ignore_interceptors || thr->in_ignored_lib
50#if SANITIZER_APPLE && !SANITIZER_GO
51 || (flags()->lock_during_write != kLockDuringAllWrites &&
52 thr->in_internal_write_call)
53#endif
54 ;
4755}
4856
4957} // namespace __tsan
lib/libtsan/tsan_interceptors_mac.cpp+19
......@@ -281,6 +281,25 @@ TSAN_INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) {
281281 Acquire(thr, pc, (uptr)lock);
282282}
283283
284// os_unfair_lock_lock_with_flags was introduced in macOS 15
285# if defined(__MAC_15_0) || defined(__IPHONE_18_0) || defined(__TVOS_18_0) || \
286 defined(__VISIONOS_2_0) || defined(__WATCHOS_11_0)
287# pragma clang diagnostic push
288# pragma clang diagnostic ignored "-Wunguarded-availability-new"
289// We're just intercepting this - if it doesn't exist on the platform, then the
290// process shouldn't have called it in the first place.
291TSAN_INTERCEPTOR(void, os_unfair_lock_lock_with_flags, os_unfair_lock_t lock,
292 os_unfair_lock_flags_t flags) {
293 if (!cur_thread()->is_inited || cur_thread()->is_dead) {
294 return REAL(os_unfair_lock_lock_with_flags)(lock, flags);
295 }
296 SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_lock_with_flags, lock, flags);
297 REAL(os_unfair_lock_lock_with_flags)(lock, flags);
298 Acquire(thr, pc, (uptr)lock);
299}
300# pragma clang diagnostic pop
301# endif
302
284303TSAN_INTERCEPTOR(void, os_unfair_lock_lock_with_options, os_unfair_lock_t lock,
285304 u32 options) {
286305 if (!cur_thread()->is_inited || cur_thread()->is_dead) {
lib/libtsan/tsan_interceptors_posix.cpp+78-32
......@@ -22,6 +22,7 @@
2222#include "sanitizer_common/sanitizer_internal_defs.h"
2323#include "sanitizer_common/sanitizer_libc.h"
2424#include "sanitizer_common/sanitizer_linux.h"
25#include "sanitizer_common/sanitizer_placement_new.h"
2526#include "sanitizer_common/sanitizer_platform_interceptors.h"
2627#include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
2728#include "sanitizer_common/sanitizer_platform_limits_posix.h"
......@@ -30,6 +31,9 @@
3031#include "sanitizer_common/sanitizer_tls_get_addr.h"
3132#include "sanitizer_common/sanitizer_vector.h"
3233#include "tsan_fd.h"
34#if SANITIZER_APPLE && !SANITIZER_GO
35# include "tsan_flags.h"
36#endif
3337#include "tsan_interceptors.h"
3438#include "tsan_interface.h"
3539#include "tsan_mman.h"
......@@ -78,17 +82,6 @@ struct ucontext_t {
7882};
7983#endif
8084
81#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 || \
82 defined(__s390x__)
83#define PTHREAD_ABI_BASE "GLIBC_2.3.2"
84#elif defined(__aarch64__) || SANITIZER_PPC64V2
85#define PTHREAD_ABI_BASE "GLIBC_2.17"
86#elif SANITIZER_LOONGARCH64
87#define PTHREAD_ABI_BASE "GLIBC_2.36"
88#elif SANITIZER_RISCV64
89# define PTHREAD_ABI_BASE "GLIBC_2.27"
90#endif
91
9285extern "C" int pthread_attr_init(void *attr);
9386extern "C" int pthread_attr_destroy(void *attr);
9487DECLARE_REAL(int, pthread_attr_getdetachstate, void *, void *)
......@@ -340,11 +333,6 @@ void ScopedInterceptor::DisableIgnoresImpl() {
340333}
341334
342335#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)
343#if SANITIZER_FREEBSD || SANITIZER_NETBSD
344# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION(func)
345#else
346# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION_VER(func, ver)
347#endif
348336#if SANITIZER_FREEBSD
349337# define TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(func) \
350338 INTERCEPT_FUNCTION(_pthread_##func)
......@@ -1145,6 +1133,22 @@ TSAN_INTERCEPTOR(int, pthread_create,
11451133
11461134TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) {
11471135 SCOPED_INTERCEPTOR_RAW(pthread_join, th, ret);
1136#if SANITIZER_ANDROID
1137 {
1138 // In Bionic, if the target thread has already exited when pthread_detach is
1139 // called, pthread_detach will call pthread_join internally to clean it up.
1140 // In that case, the thread has already been consumed by the pthread_detach
1141 // interceptor.
1142 Tid tid = ctx->thread_registry.FindThread(
1143 [](ThreadContextBase* tctx, void* arg) {
1144 return tctx->user_id == (uptr)arg;
1145 },
1146 th);
1147 if (tid == kInvalidTid) {
1148 return REAL(pthread_join)(th, ret);
1149 }
1150 }
1151#endif
11481152 Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
11491153 ThreadIgnoreBegin(thr, pc);
11501154 int res = BLOCK_REAL(pthread_join)(th, ret);
......@@ -1664,6 +1668,14 @@ TSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) {
16641668
16651669TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) {
16661670 SCOPED_INTERCEPTOR_RAW(pthread_once, o, f);
1671#if SANITIZER_APPLE && !SANITIZER_GO
1672 if (flags()->lock_during_write != kLockDuringAllWrites &&
1673 cur_thread_init()->in_internal_write_call) {
1674 // This is needed to make it through process launch without hanging
1675 f();
1676 return 0;
1677 }
1678#endif
16671679 if (o == 0 || f == 0)
16681680 return errno_EINVAL;
16691681 atomic_uint32_t *a;
......@@ -2141,13 +2153,29 @@ static void ReportErrnoSpoiling(ThreadState *thr, uptr pc, int sig) {
21412153 // StackTrace::GetNestInstructionPc(pc) is used because return address is
21422154 // expected, OutputReport() will undo this.
21432155 ObtainCurrentStack(thr, StackTrace::GetNextInstructionPc(pc), &stack);
2144 ThreadRegistryLock l(&ctx->thread_registry);
2145 ScopedReport rep(ReportTypeErrnoInSignal);
2146 rep.SetSigNum(sig);
2147 if (!IsFiredSuppression(ctx, ReportTypeErrnoInSignal, stack)) {
2148 rep.AddStack(stack, true);
2149 OutputReport(thr, rep);
2156 // Use alloca, because malloc during signal handling deadlocks
2157 ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
2158 bool suppressed;
2159 // Take a new scope as Apple platforms require the below locks released
2160 // before symbolizing in order to avoid a deadlock
2161 {
2162 ThreadRegistryLock l(&ctx->thread_registry);
2163 new (rep) ScopedReport(ReportTypeErrnoInSignal);
2164 rep->SetSigNum(sig);
2165 suppressed = IsFiredSuppression(ctx, ReportTypeErrnoInSignal, stack);
2166 if (!suppressed)
2167 rep->AddStack(stack, true);
2168#if SANITIZER_APPLE
2169 } // Close this scope to release the locks before writing report
2170#endif
2171 if (!suppressed)
2172 OutputReport(thr, *rep);
2173
2174 // Need to manually destroy this because we used placement new to allocate
2175 rep->~ScopedReport();
2176#if !SANITIZER_APPLE
21502177 }
2178#endif
21512179}
21522180
21532181static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,
......@@ -2411,7 +2439,11 @@ TSAN_INTERCEPTOR(int, vfork, int fake) {
24112439}
24122440#endif
24132441
2414#if SANITIZER_LINUX
2442#if SANITIZER_LINUX && !SANITIZER_ANDROID
2443// Bionic's pthread_create internally calls clone. When the CLONE_THREAD flag is
2444// set, clone does not create a new process but a new thread. This is a
2445// workaround for Android. Disabling the interception of clone solves the
2446// problem in most scenarios.
24152447TSAN_INTERCEPTOR(int, clone, int (*fn)(void *), void *stack, int flags,
24162448 void *arg, int *parent_tid, void *tls, pid_t *child_tid) {
24172449 SCOPED_INTERCEPTOR_RAW(clone, fn, stack, flags, arg, parent_tid, tls,
......@@ -2888,12 +2920,12 @@ TSAN_INTERCEPTOR(void, _lwp_exit) {
28882920#endif
28892921
28902922#if SANITIZER_FREEBSD
2891TSAN_INTERCEPTOR(void, thr_exit, tid_t *state) {
2923TSAN_INTERCEPTOR(void, thr_exit, ThreadID *state) {
28922924 SCOPED_TSAN_INTERCEPTOR(thr_exit, state);
28932925 DestroyThreadState();
28942926 REAL(thr_exit(state));
28952927}
2896#define TSAN_MAYBE_INTERCEPT_THR_EXIT TSAN_INTERCEPT(thr_exit)
2928# define TSAN_MAYBE_INTERCEPT_THR_EXIT TSAN_INTERCEPT(thr_exit)
28972929#else
28982930#define TSAN_MAYBE_INTERCEPT_THR_EXIT
28992931#endif
......@@ -3024,12 +3056,26 @@ void InitializeInterceptors() {
30243056 TSAN_INTERCEPT(pthread_timedjoin_np);
30253057 #endif
30263058
3027 TSAN_INTERCEPT_VER(pthread_cond_init, PTHREAD_ABI_BASE);
3028 TSAN_INTERCEPT_VER(pthread_cond_signal, PTHREAD_ABI_BASE);
3029 TSAN_INTERCEPT_VER(pthread_cond_broadcast, PTHREAD_ABI_BASE);
3030 TSAN_INTERCEPT_VER(pthread_cond_wait, PTHREAD_ABI_BASE);
3031 TSAN_INTERCEPT_VER(pthread_cond_timedwait, PTHREAD_ABI_BASE);
3032 TSAN_INTERCEPT_VER(pthread_cond_destroy, PTHREAD_ABI_BASE);
3059 // In glibc versions older than 2.36, dlsym(RTLD_NEXT, "pthread_cond_init")
3060 // may return an outdated symbol (max(2.2,base_version)) if the port was
3061 // introduced before 2.3.2 (when the new pthread_cond_t was introduced).
3062#if SANITIZER_GLIBC && !__GLIBC_PREREQ(2, 36) && \
3063 (defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 || \
3064 defined(__s390x__))
3065 INTERCEPT_FUNCTION_VER(pthread_cond_init, "GLIBC_2.3.2");
3066 INTERCEPT_FUNCTION_VER(pthread_cond_signal, "GLIBC_2.3.2");
3067 INTERCEPT_FUNCTION_VER(pthread_cond_broadcast, "GLIBC_2.3.2");
3068 INTERCEPT_FUNCTION_VER(pthread_cond_wait, "GLIBC_2.3.2");
3069 INTERCEPT_FUNCTION_VER(pthread_cond_timedwait, "GLIBC_2.3.2");
3070 INTERCEPT_FUNCTION_VER(pthread_cond_destroy, "GLIBC_2.3.2");
3071#else
3072 INTERCEPT_FUNCTION(pthread_cond_init);
3073 INTERCEPT_FUNCTION(pthread_cond_signal);
3074 INTERCEPT_FUNCTION(pthread_cond_broadcast);
3075 INTERCEPT_FUNCTION(pthread_cond_wait);
3076 INTERCEPT_FUNCTION(pthread_cond_timedwait);
3077 INTERCEPT_FUNCTION(pthread_cond_destroy);
3078#endif
30333079
30343080 TSAN_MAYBE_PTHREAD_COND_CLOCKWAIT;
30353081
......@@ -3120,7 +3166,7 @@ void InitializeInterceptors() {
31203166
31213167 TSAN_INTERCEPT(fork);
31223168 TSAN_INTERCEPT(vfork);
3123#if SANITIZER_LINUX
3169#if SANITIZER_LINUX && !SANITIZER_ANDROID
31243170 TSAN_INTERCEPT(clone);
31253171#endif
31263172#if !SANITIZER_ANDROID
lib/libtsan/tsan_interface.h+3-3
......@@ -16,7 +16,7 @@
1616#define TSAN_INTERFACE_H
1717
1818#include <sanitizer_common/sanitizer_internal_defs.h>
19using __sanitizer::tid_t;
19using __sanitizer::ThreadID;
2020using __sanitizer::uptr;
2121
2222// This header should NOT include any other headers.
......@@ -175,7 +175,7 @@ int __tsan_get_report_mutex(void *report, uptr idx, uptr *mutex_id, void **addr,
175175
176176// Returns information about threads included in the report.
177177SANITIZER_INTERFACE_ATTRIBUTE
178int __tsan_get_report_thread(void *report, uptr idx, int *tid, tid_t *os_id,
178int __tsan_get_report_thread(void *report, uptr idx, int *tid, ThreadID *os_id,
179179 int *running, const char **name, int *parent_tid,
180180 void **trace, uptr trace_size);
181181
......@@ -192,7 +192,7 @@ const char *__tsan_locate_address(uptr addr, char *name, uptr name_size,
192192// Returns the allocation stack for a heap pointer.
193193SANITIZER_INTERFACE_ATTRIBUTE
194194int __tsan_get_alloc_stack(uptr addr, uptr *trace, uptr size, int *thread_id,
195 tid_t *os_id);
195 ThreadID *os_id);
196196
197197#endif // SANITIZER_GO
198198
lib/libtsan/tsan_interface_ann.cpp+23-9
......@@ -437,16 +437,30 @@ void __tsan_mutex_post_divert(void *addr, unsigned flagz) {
437437}
438438
439439static void ReportMutexHeldWrongContext(ThreadState *thr, uptr pc) {
440 ThreadRegistryLock l(&ctx->thread_registry);
441 ScopedReport rep(ReportTypeMutexHeldWrongContext);
442 for (uptr i = 0; i < thr->mset.Size(); ++i) {
443 MutexSet::Desc desc = thr->mset.Get(i);
444 rep.AddMutex(desc.addr, desc.stack_id);
440 // Use alloca, because malloc during signal handling deadlocks
441 ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
442 // Take a new scope as Apple platforms require the below locks released
443 // before symbolizing in order to avoid a deadlock
444 {
445 ThreadRegistryLock l(&ctx->thread_registry);
446 new (rep) ScopedReport(ReportTypeMutexHeldWrongContext);
447 for (uptr i = 0; i < thr->mset.Size(); ++i) {
448 MutexSet::Desc desc = thr->mset.Get(i);
449 rep->AddMutex(desc.addr, desc.stack_id);
450 }
451 VarSizeStackTrace trace;
452 ObtainCurrentStack(thr, pc, &trace);
453 rep->AddStack(trace, true);
454#if SANITIZER_APPLE
455 } // Close this scope to release the locks
456#endif
457 OutputReport(thr, *rep);
458
459 // Need to manually destroy this because we used placement new to allocate
460 rep->~ScopedReport();
461#if !SANITIZER_APPLE
445462 }
446 VarSizeStackTrace trace;
447 ObtainCurrentStack(thr, pc, &trace);
448 rep.AddStack(trace, true);
449 OutputReport(thr, rep);
463#endif
450464}
451465
452466INTERFACE_ATTRIBUTE
lib/libtsan/tsan_mman.cpp+18-4
......@@ -182,10 +182,24 @@ static void SignalUnsafeCall(ThreadState *thr, uptr pc) {
182182 ObtainCurrentStack(thr, pc, &stack);
183183 if (IsFiredSuppression(ctx, ReportTypeSignalUnsafe, stack))
184184 return;
185 ThreadRegistryLock l(&ctx->thread_registry);
186 ScopedReport rep(ReportTypeSignalUnsafe);
187 rep.AddStack(stack, true);
188 OutputReport(thr, rep);
185 // Use alloca, because malloc during signal handling deadlocks
186 ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
187 // Take a new scope as Apple platforms require the below locks released
188 // before symbolizing in order to avoid a deadlock
189 {
190 ThreadRegistryLock l(&ctx->thread_registry);
191 new (rep) ScopedReport(ReportTypeSignalUnsafe);
192 rep->AddStack(stack, true);
193#if SANITIZER_APPLE
194 } // Close this scope to release the locks
195#endif
196 OutputReport(thr, *rep);
197
198 // Need to manually destroy this because we used placement new to allocate
199 rep->~ScopedReport();
200#if !SANITIZER_APPLE
201 }
202#endif
189203}
190204
191205
lib/libtsan/tsan_platform.h+44-7
......@@ -681,6 +681,32 @@ struct MappingGoMips64_47 {
681681 static const uptr kShadowAdd = 0x200000000000ull;
682682};
683683
684/* Go on linux/riscv64 (39-bit VMA)
6850000 0001 0000 - 000f 0000 0000: executable and heap (60 GiB)
686000f 0000 0000 - 0010 0000 0000: -
6870010 0000 0000 - 0030 0000 0000: shadow - 128 GiB ( ~ 2 * app)
6880030 0000 0000 - 0038 0000 0000: metainfo - 32 GiB ( ~ 0.5 * app)
6890038 0000 0000 - 0040 0000 0000: -
690*/
691struct MappingGoRiscv64_39 {
692 static const uptr kMetaShadowBeg = 0x003000000000ull;
693 static const uptr kMetaShadowEnd = 0x003800000000ull;
694 static const uptr kShadowBeg = 0x001000000000ull;
695 static const uptr kShadowEnd = 0x003000000000ull;
696 static const uptr kLoAppMemBeg = 0x000000010000ull;
697 static const uptr kLoAppMemEnd = 0x000f00000000ull;
698 static const uptr kMidAppMemBeg = 0;
699 static const uptr kMidAppMemEnd = 0;
700 static const uptr kHiAppMemBeg = 0;
701 static const uptr kHiAppMemEnd = 0;
702 static const uptr kHeapMemBeg = 0;
703 static const uptr kHeapMemEnd = 0;
704 static const uptr kVdsoBeg = 0;
705 static const uptr kShadowMsk = 0;
706 static const uptr kShadowXor = 0;
707 static const uptr kShadowAdd = 0x001000000000ull;
708};
709
684710/* Go on linux/riscv64 (48-bit VMA)
6857110000 0001 0000 - 00e0 0000 0000: executable and heap (896 GiB)
68671200e0 0000 0000 - 2000 0000 0000: -
......@@ -689,13 +715,13 @@ struct MappingGoMips64_47 {
6897153000 0000 0000 - 3100 0000 0000: metainfo - 1 TiB ( ~ 1 * app)
6907163100 0000 0000 - 8000 0000 0000: -
691717*/
692struct MappingGoRiscv64 {
718struct MappingGoRiscv64_48 {
693719 static const uptr kMetaShadowBeg = 0x300000000000ull;
694720 static const uptr kMetaShadowEnd = 0x310000000000ull;
695721 static const uptr kShadowBeg = 0x200000000000ull;
696722 static const uptr kShadowEnd = 0x240000000000ull;
697723 static const uptr kLoAppMemBeg = 0x000000010000ull;
698 static const uptr kLoAppMemEnd = 0x000e00000000ull;
724 static const uptr kLoAppMemEnd = 0x00e000000000ull;
699725 static const uptr kMidAppMemBeg = 0;
700726 static const uptr kMidAppMemEnd = 0;
701727 static const uptr kHiAppMemBeg = 0;
......@@ -756,7 +782,12 @@ ALWAYS_INLINE auto SelectMapping(Arg arg) {
756782# elif defined(__loongarch_lp64)
757783 return Func::template Apply<MappingGoLoongArch64_47>(arg);
758784# elif SANITIZER_RISCV64
759 return Func::template Apply<MappingGoRiscv64>(arg);
785 switch (vmaSize) {
786 case 39:
787 return Func::template Apply<MappingGoRiscv64_39>(arg);
788 case 48:
789 return Func::template Apply<MappingGoRiscv64_48>(arg);
790 }
760791# elif SANITIZER_WINDOWS
761792 return Func::template Apply<MappingGoWindows>(arg);
762793# else
......@@ -827,7 +858,8 @@ void ForEachMapping() {
827858 Func::template Apply<MappingGoAarch64>();
828859 Func::template Apply<MappingGoLoongArch64_47>();
829860 Func::template Apply<MappingGoMips64_47>();
830 Func::template Apply<MappingGoRiscv64>();
861 Func::template Apply<MappingGoRiscv64_39>();
862 Func::template Apply<MappingGoRiscv64_48>();
831863 Func::template Apply<MappingGoS390x>();
832864}
833865
......@@ -926,7 +958,9 @@ struct IsAppMemImpl {
926958};
927959
928960ALWAYS_INLINE
929bool IsAppMem(uptr mem) { return SelectMapping<IsAppMemImpl>(mem); }
961bool IsAppMem(uptr mem) {
962 return SelectMapping<IsAppMemImpl>(STRIP_MTE_TAG(mem));
963}
930964
931965struct IsShadowMemImpl {
932966 template <typename Mapping>
......@@ -965,7 +999,8 @@ struct MemToShadowImpl {
965999
9661000ALWAYS_INLINE
9671001RawShadow *MemToShadow(uptr x) {
968 return reinterpret_cast<RawShadow *>(SelectMapping<MemToShadowImpl>(x));
1002 return reinterpret_cast<RawShadow*>(
1003 SelectMapping<MemToShadowImpl>(STRIP_MTE_TAG(x)));
9691004}
9701005
9711006struct MemToMetaImpl {
......@@ -979,7 +1014,9 @@ struct MemToMetaImpl {
9791014};
9801015
9811016ALWAYS_INLINE
982u32 *MemToMeta(uptr x) { return SelectMapping<MemToMetaImpl>(x); }
1017u32* MemToMeta(uptr x) {
1018 return SelectMapping<MemToMetaImpl>(STRIP_MTE_TAG(x));
1019}
9831020
9841021struct ShadowToMemImpl {
9851022 template <typename Mapping>
lib/libtsan/tsan_platform_linux.cpp+42-14
......@@ -393,9 +393,9 @@ void InitializePlatformEarly() {
393393 Die();
394394 }
395395# else
396 if (vmaSize != 48) {
396 if (vmaSize != 39 && vmaSize != 48) {
397397 Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
398 Printf("FATAL: Found %zd - Supported 48\n", vmaSize);
398 Printf("FATAL: Found %zd - Supported 39 and 48\n", vmaSize);
399399 Die();
400400 }
401401# endif
......@@ -415,7 +415,7 @@ void InitializePlatform() {
415415 // is not compiled with -pie.
416416#if !SANITIZER_GO
417417 {
418# if SANITIZER_LINUX && (defined(__aarch64__) || defined(__loongarch_lp64))
418# if INIT_LONGJMP_XOR_KEY
419419 // Initialize the xor key used in {sig}{set,long}jump.
420420 InitializeLongjmpXorKey();
421421# endif
......@@ -486,8 +486,20 @@ int ExtractRecvmsgFDs(void *msgp, int *fds, int nfd) {
486486
487487// Reverse operation of libc stack pointer mangling
488488static uptr UnmangleLongJmpSp(uptr mangled_sp) {
489#if defined(__x86_64__)
490# if SANITIZER_LINUX
489# if SANITIZER_ANDROID && INIT_LONGJMP_XOR_KEY
490 if (longjmp_xor_key == 0) {
491 // bionic libc initialization process: __libc_init_globals ->
492 // __libc_init_vdso (calls strcmp) -> __libc_init_setjmp_cookie. strcmp is
493 // intercepted by TSan, so during TSan initialization the setjmp_cookie
494 // remains uninitialized. On Android, longjmp_xor_key must be set on first
495 // use.
496 InitializeLongjmpXorKey();
497 CHECK_NE(longjmp_xor_key, 0);
498 }
499# endif
500
501# if defined(__x86_64__)
502# if SANITIZER_LINUX
491503 // Reverse of:
492504 // xor %fs:0x30, %rsi
493505 // rol $0x11, %rsi
......@@ -542,13 +554,23 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
542554# else
543555# define LONG_JMP_SP_ENV_SLOT 2
544556# endif
545#elif SANITIZER_LINUX
546# ifdef __aarch64__
547# define LONG_JMP_SP_ENV_SLOT 13
548# elif defined(__loongarch__)
549# define LONG_JMP_SP_ENV_SLOT 1
550# elif defined(__mips64)
551# define LONG_JMP_SP_ENV_SLOT 1
557# elif SANITIZER_ANDROID
558# ifdef __aarch64__
559# define LONG_JMP_SP_ENV_SLOT 3
560# elif SANITIZER_RISCV64
561# define LONG_JMP_SP_ENV_SLOT 3
562# elif defined(__x86_64__)
563# define LONG_JMP_SP_ENV_SLOT 6
564# else
565# error unsupported
566# endif
567# elif SANITIZER_LINUX
568# ifdef __aarch64__
569# define LONG_JMP_SP_ENV_SLOT 13
570# elif defined(__loongarch__)
571# define LONG_JMP_SP_ENV_SLOT 1
572# elif defined(__mips64)
573# define LONG_JMP_SP_ENV_SLOT 1
552574# elif SANITIZER_RISCV64
553575# define LONG_JMP_SP_ENV_SLOT 13
554576# elif defined(__s390x__)
......@@ -556,7 +578,7 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
556578# else
557579# define LONG_JMP_SP_ENV_SLOT 6
558580# endif
559#endif
581# endif
560582
561583uptr ExtractLongJmpSp(uptr *env) {
562584 uptr mangled_sp = env[LONG_JMP_SP_ENV_SLOT];
......@@ -653,7 +675,13 @@ ThreadState *cur_thread() {
653675 }
654676 CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &oldset, nullptr));
655677 }
656 return thr;
678
679 // Skia calls mallopt(M_THREAD_DISABLE_MEM_INIT, 1), which sets the least
680 // significant bit of TLS_SLOT_SANITIZER to 1. Scudo allocator uses this bit
681 // as a flag to disable memory initialization. This is a workaround to get the
682 // correct ThreadState pointer.
683 uptr addr = reinterpret_cast<uptr>(thr);
684 return reinterpret_cast<ThreadState*>(addr & ~1ULL);
657685}
658686
659687void set_cur_thread(ThreadState *thr) {
lib/libtsan/tsan_platform_mac.cpp+16-3
......@@ -226,9 +226,20 @@ static void ThreadTerminateCallback(uptr thread) {
226226void InitializePlatformEarly() {
227227# if !SANITIZER_GO && SANITIZER_IOS
228228 uptr max_vm = GetMaxUserVirtualAddress() + 1;
229 if (max_vm != HiAppMemEnd()) {
230 Printf("ThreadSanitizer: unsupported vm address limit %p, expected %p.\n",
231 (void *)max_vm, (void *)HiAppMemEnd());
229 if (max_vm < HiAppMemEnd()) {
230 Report(
231 "ThreadSanitizer: Unsupported virtual memory layout:\n\tVM address "
232 "limit = %p\n\tExpected %p.\n",
233 (void*)max_vm, (void*)HiAppMemEnd());
234 Die();
235 }
236 // In some configurations, the max_vm is expanded, but much of this space is
237 // already mapped. TSAN will not work in this configuration.
238 if (!MemoryRangeIsAvailable(HiAppMemEnd() - 1, HiAppMemEnd() - 1)) {
239 Report(
240 "ThreadSanitizer: Unsupported virtual memory layout: Address %p is "
241 "already mapped.\n",
242 (void*)(HiAppMemEnd() - 1));
232243 Die();
233244 }
234245#endif
......@@ -248,7 +259,9 @@ void InitializePlatform() {
248259
249260 ThreadEventCallbacks callbacks = {
250261 .create = ThreadCreateCallback,
262 .start = nullptr,
251263 .terminate = ThreadTerminateCallback,
264 .destroy = nullptr,
252265 };
253266 InstallPthreadIntrospectionHook(callbacks);
254267#endif
lib/libtsan/tsan_report.h+14-1
......@@ -12,6 +12,8 @@
1212#ifndef TSAN_REPORT_H
1313#define TSAN_REPORT_H
1414
15#include "sanitizer_common/sanitizer_internal_defs.h"
16#include "sanitizer_common/sanitizer_stacktrace.h"
1517#include "sanitizer_common/sanitizer_symbolizer.h"
1618#include "sanitizer_common/sanitizer_thread_registry.h"
1719#include "sanitizer_common/sanitizer_vector.h"
......@@ -56,6 +58,7 @@ struct ReportMop {
5658 bool atomic;
5759 uptr external_tag;
5860 Vector<ReportMopMutex> mset;
61 StackTrace stack_trace;
5962 ReportStack *stack;
6063
6164 ReportMop();
......@@ -79,25 +82,34 @@ struct ReportLocation {
7982 int fd = 0;
8083 bool fd_closed = false;
8184 bool suppressable = false;
85 StackID stack_id = 0;
8286 ReportStack *stack = nullptr;
8387};
8488
8589struct ReportThread {
8690 Tid id;
87 tid_t os_id;
91 ThreadID os_id;
8892 bool running;
8993 ThreadType thread_type;
9094 char *name;
9195 Tid parent_tid;
96 StackID stack_id;
9297 ReportStack *stack;
98 bool suppressable;
9399};
94100
95101struct ReportMutex {
96102 int id;
97103 uptr addr;
104 StackID stack_id;
98105 ReportStack *stack;
99106};
100107
108struct AddedLocationAddr {
109 uptr addr;
110 usize locs_idx;
111};
112
101113class ReportDesc {
102114 public:
103115 ReportType typ;
......@@ -105,6 +117,7 @@ class ReportDesc {
105117 Vector<ReportStack*> stacks;
106118 Vector<ReportMop*> mops;
107119 Vector<ReportLocation*> locs;
120 Vector<AddedLocationAddr> added_location_addrs;
108121 Vector<ReportMutex*> mutexes;
109122 Vector<ReportThread*> threads;
110123 Vector<Tid> unique_tids;
lib/libtsan/tsan_rtl.cpp+14
......@@ -40,6 +40,13 @@ SANITIZER_WEAK_DEFAULT_IMPL
4040void __tsan_test_only_on_fork() {}
4141#endif
4242
43#if SANITIZER_APPLE && !SANITIZER_GO
44// Override weak symbol from sanitizer_common
45extern void __tsan_set_in_internal_write_call(bool value) {
46 __tsan::cur_thread_init()->in_internal_write_call = value;
47}
48#endif
49
4350namespace __tsan {
4451
4552#if !SANITIZER_GO
......@@ -893,6 +900,13 @@ void ForkChildAfter(ThreadState* thr, uptr pc, bool start_thread) {
893900 ThreadIgnoreBegin(thr, pc);
894901 ThreadIgnoreSyncBegin(thr, pc);
895902 }
903
904# if SANITIZER_APPLE && !SANITIZER_GO
905 // This flag can have inheritance disabled - we are the child so act
906 // accordingly
907 if (flags()->lock_during_write == kNoLockDuringWritesCurrentProcess)
908 flags()->lock_during_write = kLockDuringAllWrites;
909# endif
896910}
897911#endif
898912
lib/libtsan/tsan_rtl.h+7-2
......@@ -236,6 +236,10 @@ struct alignas(SANITIZER_CACHE_LINE_SIZE) ThreadState {
236236
237237 const ReportDesc *current_report;
238238
239#if SANITIZER_APPLE && !SANITIZER_GO
240 bool in_internal_write_call;
241#endif
242
239243 explicit ThreadState(Tid tid);
240244};
241245
......@@ -420,6 +424,7 @@ class ScopedReportBase {
420424 void AddSleep(StackID stack_id);
421425 void SetCount(int count);
422426 void SetSigNum(int sig);
427 void SymbolizeStackElems(void);
423428
424429 const ReportDesc *GetReport() const;
425430
......@@ -498,7 +503,7 @@ void ForkChildAfter(ThreadState *thr, uptr pc, bool start_thread);
498503
499504void ReportRace(ThreadState *thr, RawShadow *shadow_mem, Shadow cur, Shadow old,
500505 AccessType typ);
501bool OutputReport(ThreadState *thr, const ScopedReport &srep);
506bool OutputReport(ThreadState *thr, ScopedReport &srep);
502507bool IsFiredSuppression(Context *ctx, ReportType type, StackTrace trace);
503508bool IsExpectedReport(uptr addr, uptr size);
504509
......@@ -559,7 +564,7 @@ void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc);
559564void ThreadIgnoreSyncEnd(ThreadState *thr);
560565
561566Tid ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached);
562void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,
567void ThreadStart(ThreadState *thr, Tid tid, ThreadID os_id,
563568 ThreadType thread_type);
564569void ThreadFinish(ThreadState *thr);
565570Tid ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid);
lib/libtsan/tsan_rtl_aarch64.S+3-5
......@@ -4,10 +4,8 @@
44#include "sanitizer_common/sanitizer_asm.h"
55#include "builtins/assembly.h"
66
7#if !defined(__APPLE__)
8.section .text
9#else
10.section __TEXT,__text
7TEXT_SECTION
8#if defined(__APPLE__)
119.align 3
1210#endif
1311
......@@ -222,6 +220,6 @@ ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))
222220
223221NO_EXEC_STACK_DIRECTIVE
224222
225GNU_PROPERTY_BTI_PAC
223GNU_PROPERTY_BTI_PAC_GCS
226224
227225#endif
lib/libtsan/tsan_rtl_access.cpp+8-3
......@@ -419,6 +419,11 @@ NOINLINE void TraceRestartMemoryAccess(ThreadState* thr, uptr pc, uptr addr,
419419
420420ALWAYS_INLINE USED void MemoryAccess(ThreadState* thr, uptr pc, uptr addr,
421421 uptr size, AccessType typ) {
422#if SANITIZER_APPLE && !SANITIZER_GO
423 // Swift symbolizer can be intercepted and deadlock without this
424 if (thr->in_symbolizer)
425 return;
426#endif
422427 RawShadow* shadow_mem = MemToShadow(addr);
423428 UNUSED char memBuf[4][64];
424429 DPrintf2("#%d: Access: %d@%d %p/%zd typ=0x%x {%s, %s, %s, %s}\n", thr->tid,
......@@ -684,7 +689,7 @@ void MemoryAccessRangeT(ThreadState* thr, uptr pc, uptr addr, uptr size) {
684689 DCHECK(IsAppMem(addr + size - 1));
685690 }
686691 if (!IsShadowMem(shadow_mem)) {
687 Printf("Bad shadow start addr: %p (%p)\n", shadow_mem, (void*)addr);
692 Printf("Bad shadow start addr: %p (%p)\n", (void*)shadow_mem, (void*)addr);
688693 DCHECK(IsShadowMem(shadow_mem));
689694 }
690695
......@@ -693,12 +698,12 @@ void MemoryAccessRangeT(ThreadState* thr, uptr pc, uptr addr, uptr size) {
693698 RawShadow* shadow_mem_end =
694699 shadow_mem + rounded_size / kShadowCell * kShadowCnt;
695700 if (!IsShadowMem(shadow_mem_end - 1)) {
696 Printf("Bad shadow end addr: %p (%p)\n", shadow_mem_end - 1,
701 Printf("Bad shadow end addr: %p (%p)\n", (void*)(shadow_mem_end - 1),
697702 (void*)(addr + size - 1));
698703 Printf(
699704 "Shadow start addr (ok): %p (%p); size: 0x%zx; rounded_size: 0x%zx; "
700705 "kShadowMultiplier: %zx\n",
701 shadow_mem, (void*)addr, size, rounded_size, kShadowMultiplier);
706 (void*)shadow_mem, (void*)addr, size, rounded_size, kShadowMultiplier);
702707 DCHECK(IsShadowMem(shadow_mem_end - 1));
703708 }
704709#endif
lib/libtsan/tsan_rtl_amd64.S+2
......@@ -3,6 +3,8 @@
33
44#include "sanitizer_common/sanitizer_asm.h"
55
6.att_syntax
7
68#if !defined(__APPLE__)
79.section .text
810#else
lib/libtsan/tsan_rtl_mutex.cpp+94-49
......@@ -11,14 +11,15 @@
1111//===----------------------------------------------------------------------===//
1212
1313#include <sanitizer_common/sanitizer_deadlock_detector_interface.h>
14#include <sanitizer_common/sanitizer_placement_new.h>
1415#include <sanitizer_common/sanitizer_stackdepot.h>
1516
16#include "tsan_rtl.h"
1717#include "tsan_flags.h"
18#include "tsan_sync.h"
18#include "tsan_platform.h"
1919#include "tsan_report.h"
20#include "tsan_rtl.h"
2021#include "tsan_symbolize.h"
21#include "tsan_platform.h"
22#include "tsan_sync.h"
2223
2324namespace __tsan {
2425
......@@ -55,14 +56,28 @@ static void ReportMutexMisuse(ThreadState *thr, uptr pc, ReportType typ,
5556 return;
5657 if (!ShouldReport(thr, typ))
5758 return;
58 ThreadRegistryLock l(&ctx->thread_registry);
59 ScopedReport rep(typ);
60 rep.AddMutex(addr, creation_stack_id);
61 VarSizeStackTrace trace;
62 ObtainCurrentStack(thr, pc, &trace);
63 rep.AddStack(trace, true);
64 rep.AddLocation(addr, 1);
65 OutputReport(thr, rep);
59 // Use alloca, because malloc during signal handling deadlocks
60 ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
61 // Take a new scope as Apple platforms require the below locks released
62 // before symbolizing in order to avoid a deadlock
63 {
64 ThreadRegistryLock l(&ctx->thread_registry);
65 new (rep) ScopedReport(typ);
66 rep->AddMutex(addr, creation_stack_id);
67 VarSizeStackTrace trace;
68 ObtainCurrentStack(thr, pc, &trace);
69 rep->AddStack(trace, true);
70 rep->AddLocation(addr, 1);
71#if SANITIZER_APPLE
72 } // Close this scope to release the locks
73#endif
74 OutputReport(thr, *rep);
75
76 // Need to manually destroy this because we used placement new to allocate
77 rep->~ScopedReport();
78#if !SANITIZER_APPLE
79 }
80#endif
6681}
6782
6883static void RecordMutexLock(ThreadState *thr, uptr pc, uptr addr,
......@@ -528,51 +543,81 @@ void AfterSleep(ThreadState *thr, uptr pc) {
528543void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) {
529544 if (r == 0 || !ShouldReport(thr, ReportTypeDeadlock))
530545 return;
531 ThreadRegistryLock l(&ctx->thread_registry);
532 ScopedReport rep(ReportTypeDeadlock);
533 for (int i = 0; i < r->n; i++) {
534 rep.AddMutex(r->loop[i].mtx_ctx0, r->loop[i].stk[0]);
535 rep.AddUniqueTid((int)r->loop[i].thr_ctx);
536 rep.AddThread((int)r->loop[i].thr_ctx);
537 }
538 uptr dummy_pc = 0x42;
539 for (int i = 0; i < r->n; i++) {
540 for (int j = 0; j < (flags()->second_deadlock_stack ? 2 : 1); j++) {
541 u32 stk = r->loop[i].stk[j];
542 if (stk && stk != kInvalidStackID) {
543 rep.AddStack(StackDepotGet(stk), true);
544 } else {
545 // Sometimes we fail to extract the stack trace (FIXME: investigate),
546 // but we should still produce some stack trace in the report.
547 rep.AddStack(StackTrace(&dummy_pc, 1), true);
546 // Use alloca, because malloc during signal handling deadlocks
547 ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
548 // Take a new scope as Apple platforms require the below locks released
549 // before symbolizing in order to avoid a deadlock
550 {
551 ThreadRegistryLock l(&ctx->thread_registry);
552 new (rep) ScopedReport(ReportTypeDeadlock);
553 for (int i = 0; i < r->n; i++) {
554 rep->AddMutex(r->loop[i].mtx_ctx0, r->loop[i].stk[0]);
555 rep->AddUniqueTid((int)r->loop[i].thr_ctx);
556 rep->AddThread((int)r->loop[i].thr_ctx);
557 }
558 uptr dummy_pc = 0x42;
559 for (int i = 0; i < r->n; i++) {
560 for (int j = 0; j < (flags()->second_deadlock_stack ? 2 : 1); j++) {
561 u32 stk = r->loop[i].stk[j];
562 StackTrace stack;
563 if (stk && stk != kInvalidStackID) {
564 stack = StackDepotGet(stk);
565 } else {
566 // Sometimes we fail to extract the stack trace (FIXME: investigate),
567 // but we should still produce some stack trace in the report.
568 stack = StackTrace(&dummy_pc, 1);
569 }
570 rep->AddStack(stack, true);
548571 }
549572 }
573#if SANITIZER_APPLE
574 } // Close this scope to release the locks
575#endif
576 OutputReport(thr, *rep);
577
578 // Need to manually destroy this because we used placement new to allocate
579 rep->~ScopedReport();
580#if !SANITIZER_APPLE
550581 }
551 OutputReport(thr, rep);
582#endif
552583}
553584
554585void ReportDestroyLocked(ThreadState *thr, uptr pc, uptr addr,
555586 FastState last_lock, StackID creation_stack_id) {
556 // We need to lock the slot during RestoreStack because it protects
557 // the slot journal.
558 Lock slot_lock(&ctx->slots[static_cast<uptr>(last_lock.sid())].mtx);
559 ThreadRegistryLock l0(&ctx->thread_registry);
560 Lock slots_lock(&ctx->slot_mtx);
561 ScopedReport rep(ReportTypeMutexDestroyLocked);
562 rep.AddMutex(addr, creation_stack_id);
563 VarSizeStackTrace trace;
564 ObtainCurrentStack(thr, pc, &trace);
565 rep.AddStack(trace, true);
566
567 Tid tid;
568 DynamicMutexSet mset;
569 uptr tag;
570 if (!RestoreStack(EventType::kLock, last_lock.sid(), last_lock.epoch(), addr,
571 0, kAccessWrite, &tid, &trace, mset, &tag))
572 return;
573 rep.AddStack(trace, true);
574 rep.AddLocation(addr, 1);
575 OutputReport(thr, rep);
587 // Use alloca, because malloc during signal handling deadlocks
588 ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
589 // Take a new scope as Apple platforms require the below locks released
590 // before symbolizing in order to avoid a deadlock
591 {
592 // We need to lock the slot during RestoreStack because it protects
593 // the slot journal.
594 Lock slot_lock(&ctx->slots[static_cast<uptr>(last_lock.sid())].mtx);
595 ThreadRegistryLock l0(&ctx->thread_registry);
596 Lock slots_lock(&ctx->slot_mtx);
597 new (rep) ScopedReport(ReportTypeMutexDestroyLocked);
598 rep->AddMutex(addr, creation_stack_id);
599 VarSizeStackTrace trace;
600 ObtainCurrentStack(thr, pc, &trace);
601 rep->AddStack(trace, true);
602
603 Tid tid;
604 DynamicMutexSet mset;
605 uptr tag;
606 if (!RestoreStack(EventType::kLock, last_lock.sid(), last_lock.epoch(),
607 addr, 0, kAccessWrite, &tid, &trace, mset, &tag))
608 return;
609 rep->AddStack(trace, true);
610 rep->AddLocation(addr, 1);
611#if SANITIZER_APPLE
612 } // Close this scope to release the locks
613#endif
614 OutputReport(thr, *rep);
615
616 // Need to manually destroy this because we used placement new to allocate
617 rep->~ScopedReport();
618#if !SANITIZER_APPLE
619 }
620#endif
576621}
577622
578623} // namespace __tsan
lib/libtsan/tsan_rtl_report.cpp+132-65
......@@ -11,10 +11,12 @@
1111//===----------------------------------------------------------------------===//
1212
1313#include "sanitizer_common/sanitizer_common.h"
14#include "sanitizer_common/sanitizer_internal_defs.h"
1415#include "sanitizer_common/sanitizer_libc.h"
1516#include "sanitizer_common/sanitizer_placement_new.h"
1617#include "sanitizer_common/sanitizer_stackdepot.h"
1718#include "sanitizer_common/sanitizer_stacktrace.h"
19#include "tsan_defs.h"
1820#include "tsan_fd.h"
1921#include "tsan_flags.h"
2022#include "tsan_mman.h"
......@@ -109,7 +111,13 @@ static ReportStack *SymbolizeStack(StackTrace trace) {
109111 // instruction.
110112 if ((pc & kExternalPCBit) == 0)
111113 pc1 = StackTrace::GetPreviousInstructionPc(pc);
112 SymbolizedStack *ent = SymbolizeCode(pc1);
114 SymbolizedStack* ent = SymbolizeCode(pc1, si == trace.size - 1);
115#if SANITIZER_GO
116 if (ent == nullptr) {
117 // Go might have 0 frames for this PC (wrapper frames aren't reported).
118 continue;
119 }
120#endif
113121 CHECK_NE(ent, 0);
114122 SymbolizedStack *last = ent;
115123 while (last->next) {
......@@ -187,10 +195,8 @@ void ScopedReportBase::AddMemoryAccess(uptr addr, uptr external_tag, Shadow s,
187195 mop->size = size;
188196 mop->write = !(typ & kAccessRead);
189197 mop->atomic = typ & kAccessAtomic;
190 mop->stack = SymbolizeStack(stack);
191198 mop->external_tag = external_tag;
192 if (mop->stack)
193 mop->stack->suppressable = true;
199 mop->stack_trace = stack;
194200 for (uptr i = 0; i < mset->Size(); i++) {
195201 MutexSet::Desc d = mset->Get(i);
196202 int id = this->AddMutex(d.addr, d.stack_id);
......@@ -199,6 +205,56 @@ void ScopedReportBase::AddMemoryAccess(uptr addr, uptr external_tag, Shadow s,
199205 }
200206}
201207
208void ScopedReportBase::SymbolizeStackElems() {
209 // symbolize memory ops
210 for (usize i = 0, size = rep_->mops.Size(); i < size; i++) {
211 ReportMop *mop = rep_->mops[i];
212 mop->stack = SymbolizeStack(mop->stack_trace);
213 if (mop->stack)
214 mop->stack->suppressable = true;
215 }
216
217 // symbolize locations
218 for (usize i = 0, size = rep_->locs.Size(); i < size; i++) {
219 // added locations have a NULL placeholder - don't dereference them
220 if (ReportLocation *loc = rep_->locs[i])
221 loc->stack = SymbolizeStackId(loc->stack_id);
222 }
223
224 // symbolize any added locations
225 for (usize i = 0, size = rep_->added_location_addrs.Size(); i < size; i++) {
226 AddedLocationAddr *added_loc = &rep_->added_location_addrs[i];
227 if (ReportLocation *loc = SymbolizeData(added_loc->addr)) {
228 loc->suppressable = true;
229 rep_->locs[added_loc->locs_idx] = loc;
230 }
231 }
232
233 // Filter out any added location placeholders that could not be symbolized
234 usize j = 0;
235 for (usize i = 0, size = rep_->locs.Size(); i < size; i++) {
236 if (rep_->locs[i] != nullptr) {
237 rep_->locs[j] = rep_->locs[i];
238 j++;
239 }
240 }
241 rep_->locs.Resize(j);
242
243 // symbolize threads
244 for (usize i = 0, size = rep_->threads.Size(); i < size; i++) {
245 ReportThread *rt = rep_->threads[i];
246 rt->stack = SymbolizeStackId(rt->stack_id);
247 if (rt->stack)
248 rt->stack->suppressable = rt->suppressable;
249 }
250
251 // symbolize mutexes
252 for (usize i = 0, size = rep_->mutexes.Size(); i < size; i++) {
253 ReportMutex *rm = rep_->mutexes[i];
254 rm->stack = SymbolizeStackId(rm->stack_id);
255 }
256}
257
202258void ScopedReportBase::AddUniqueTid(Tid unique_tid) {
203259 rep_->unique_tids.PushBack(unique_tid);
204260}
......@@ -216,10 +272,8 @@ void ScopedReportBase::AddThread(const ThreadContext *tctx, bool suppressable) {
216272 rt->name = internal_strdup(tctx->name);
217273 rt->parent_tid = tctx->parent_tid;
218274 rt->thread_type = tctx->thread_type;
219 rt->stack = 0;
220 rt->stack = SymbolizeStackId(tctx->creation_stack_id);
221 if (rt->stack)
222 rt->stack->suppressable = suppressable;
275 rt->stack_id = tctx->creation_stack_id;
276 rt->suppressable = suppressable;
223277}
224278
225279#if !SANITIZER_GO
......@@ -270,7 +324,7 @@ int ScopedReportBase::AddMutex(uptr addr, StackID creation_stack_id) {
270324 rep_->mutexes.PushBack(rm);
271325 rm->id = rep_->mutexes.Size() - 1;
272326 rm->addr = addr;
273 rm->stack = SymbolizeStackId(creation_stack_id);
327 rm->stack_id = creation_stack_id;
274328 return rm->id;
275329}
276330
......@@ -288,7 +342,7 @@ void ScopedReportBase::AddLocation(uptr addr, uptr size) {
288342 loc->fd_closed = closed;
289343 loc->fd = fd;
290344 loc->tid = creat_tid;
291 loc->stack = SymbolizeStackId(creat_stack);
345 loc->stack_id = creat_stack;
292346 rep_->locs.PushBack(loc);
293347 AddThread(creat_tid);
294348 return;
......@@ -310,7 +364,7 @@ void ScopedReportBase::AddLocation(uptr addr, uptr size) {
310364 loc->heap_chunk_size = b->siz;
311365 loc->external_tag = b->tag;
312366 loc->tid = b->tid;
313 loc->stack = SymbolizeStackId(b->stk);
367 loc->stack_id = b->stk;
314368 rep_->locs.PushBack(loc);
315369 AddThread(b->tid);
316370 return;
......@@ -324,11 +378,8 @@ void ScopedReportBase::AddLocation(uptr addr, uptr size) {
324378 AddThread(tctx);
325379 }
326380#endif
327 if (ReportLocation *loc = SymbolizeData(addr)) {
328 loc->suppressable = true;
329 rep_->locs.PushBack(loc);
330 return;
331 }
381 rep_->added_location_addrs.PushBack({addr, rep_->locs.Size()});
382 rep_->locs.PushBack(nullptr);
332383}
333384
334385#if !SANITIZER_GO
......@@ -628,11 +679,12 @@ static bool HandleRacyStacks(ThreadState *thr, VarSizeStackTrace traces[2]) {
628679 return false;
629680}
630681
631bool OutputReport(ThreadState *thr, const ScopedReport &srep) {
682bool OutputReport(ThreadState *thr, ScopedReport &srep) {
632683 // These should have been checked in ShouldReport.
633684 // It's too late to check them here, we have already taken locks.
634685 CHECK(flags()->report_bugs);
635686 CHECK(!thr->suppress_reports);
687 srep.SymbolizeStackElems();
636688 atomic_store_relaxed(&ctx->last_symbolize_time_ns, NanoTime());
637689 const ReportDesc *rep = srep.GetReport();
638690 CHECK_EQ(thr->current_report, nullptr);
......@@ -761,65 +813,80 @@ void ReportRace(ThreadState *thr, RawShadow *shadow_mem, Shadow cur, Shadow old,
761813 DynamicMutexSet mset1;
762814 MutexSet *mset[kMop] = {&thr->mset, mset1};
763815
764 // We need to lock the slot during RestoreStack because it protects
765 // the slot journal.
766 Lock slot_lock(&ctx->slots[static_cast<uptr>(s[1].sid())].mtx);
767 ThreadRegistryLock l0(&ctx->thread_registry);
768 Lock slots_lock(&ctx->slot_mtx);
769 if (SpuriousRace(old))
770 return;
771 if (!RestoreStack(EventType::kAccessExt, s[1].sid(), s[1].epoch(), addr1,
772 size1, typ1, &tids[1], &traces[1], mset[1], &tags[1])) {
773 StoreShadow(&ctx->last_spurious_race, old.raw());
774 return;
775 }
816 // Use alloca, because malloc during signal handling deadlocks
817 ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
818 // Take a new scope as Apple platforms require the below locks released
819 // before symbolizing in order to avoid a deadlock
820 {
821 // We need to lock the slot during RestoreStack because it protects
822 // the slot journal.
823 Lock slot_lock(&ctx->slots[static_cast<uptr>(s[1].sid())].mtx);
824 ThreadRegistryLock l0(&ctx->thread_registry);
825 Lock slots_lock(&ctx->slot_mtx);
826 if (SpuriousRace(old))
827 return;
828 if (!RestoreStack(EventType::kAccessExt, s[1].sid(), s[1].epoch(), addr1,
829 size1, typ1, &tids[1], &traces[1], mset[1], &tags[1])) {
830 StoreShadow(&ctx->last_spurious_race, old.raw());
831 return;
832 }
776833
777 if (IsFiredSuppression(ctx, rep_typ, traces[1]))
778 return;
834 if (IsFiredSuppression(ctx, rep_typ, traces[1]))
835 return;
779836
780 if (HandleRacyStacks(thr, traces))
781 return;
837 if (HandleRacyStacks(thr, traces))
838 return;
782839
783 // If any of the accesses has a tag, treat this as an "external" race.
784 uptr tag = kExternalTagNone;
785 for (uptr i = 0; i < kMop; i++) {
786 if (tags[i] != kExternalTagNone) {
787 rep_typ = ReportTypeExternalRace;
788 tag = tags[i];
789 break;
840 // If any of the accesses has a tag, treat this as an "external" race.
841 uptr tag = kExternalTagNone;
842 for (uptr i = 0; i < kMop; i++) {
843 if (tags[i] != kExternalTagNone) {
844 rep_typ = ReportTypeExternalRace;
845 tag = tags[i];
846 break;
847 }
790848 }
791 }
792849
793 ScopedReport rep(rep_typ, tag);
794 for (uptr i = 0; i < kMop; i++)
795 rep.AddMemoryAccess(addr, tags[i], s[i], tids[i], traces[i], mset[i]);
850 new (rep) ScopedReport(rep_typ, tag);
851 for (uptr i = 0; i < kMop; i++)
852 rep->AddMemoryAccess(addr, tags[i], s[i], tids[i], traces[i], mset[i]);
796853
797 for (uptr i = 0; i < kMop; i++) {
798 ThreadContext *tctx = static_cast<ThreadContext *>(
799 ctx->thread_registry.GetThreadLocked(tids[i]));
800 rep.AddThread(tctx);
801 }
854 for (uptr i = 0; i < kMop; i++) {
855 ThreadContext *tctx = static_cast<ThreadContext *>(
856 ctx->thread_registry.GetThreadLocked(tids[i]));
857 rep->AddThread(tctx);
858 }
802859
803 rep.AddLocation(addr_min, addr_max - addr_min);
804
805 if (flags()->print_full_thread_history) {
806 const ReportDesc *rep_desc = rep.GetReport();
807 for (uptr i = 0; i < rep_desc->threads.Size(); i++) {
808 Tid parent_tid = rep_desc->threads[i]->parent_tid;
809 if (parent_tid == kMainTid || parent_tid == kInvalidTid)
810 continue;
811 ThreadContext *parent_tctx = static_cast<ThreadContext *>(
812 ctx->thread_registry.GetThreadLocked(parent_tid));
813 rep.AddThread(parent_tctx);
860 rep->AddLocation(addr_min, addr_max - addr_min);
861
862 if (flags()->print_full_thread_history) {
863 const ReportDesc *rep_desc = rep->GetReport();
864 for (uptr i = 0; i < rep_desc->threads.Size(); i++) {
865 Tid parent_tid = rep_desc->threads[i]->parent_tid;
866 if (parent_tid == kMainTid || parent_tid == kInvalidTid)
867 continue;
868 ThreadContext *parent_tctx = static_cast<ThreadContext *>(
869 ctx->thread_registry.GetThreadLocked(parent_tid));
870 rep->AddThread(parent_tctx);
871 }
814872 }
815 }
816873
817874#if !SANITIZER_GO
818 if (!((typ0 | typ1) & kAccessFree) &&
819 s[1].epoch() <= thr->last_sleep_clock.Get(s[1].sid()))
820 rep.AddSleep(thr->last_sleep_stack_id);
875 if (!((typ0 | typ1) & kAccessFree) &&
876 s[1].epoch() <= thr->last_sleep_clock.Get(s[1].sid()))
877 rep->AddSleep(thr->last_sleep_stack_id);
878#endif
879
880#if SANITIZER_APPLE
881 } // Close this scope to release the locks
882#endif
883 OutputReport(thr, *rep);
884
885 // Need to manually destroy this because we used placement new to allocate
886 rep->~ScopedReport();
887#if !SANITIZER_APPLE
888 }
821889#endif
822 OutputReport(thr, rep);
823890}
824891
825892void PrintCurrentStack(ThreadState *thr, uptr pc) {
lib/libtsan/tsan_rtl_thread.cpp+31-9
......@@ -88,15 +88,33 @@ void ThreadFinalize(ThreadState *thr) {
8888#if !SANITIZER_GO
8989 if (!ShouldReport(thr, ReportTypeThreadLeak))
9090 return;
91 ThreadRegistryLock l(&ctx->thread_registry);
9291 Vector<ThreadLeak> leaks;
93 ctx->thread_registry.RunCallbackForEachThreadLocked(CollectThreadLeaks,
94 &leaks);
92 {
93 ThreadRegistryLock l(&ctx->thread_registry);
94 ctx->thread_registry.RunCallbackForEachThreadLocked(CollectThreadLeaks,
95 &leaks);
96 }
97
9598 for (uptr i = 0; i < leaks.Size(); i++) {
96 ScopedReport rep(ReportTypeThreadLeak);
97 rep.AddThread(leaks[i].tctx, true);
98 rep.SetCount(leaks[i].count);
99 OutputReport(thr, rep);
99 // Use alloca, because malloc during signal handling deadlocks
100 ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
101 // Take a new scope as Apple platforms require the below locks released
102 // before symbolizing in order to avoid a deadlock
103 {
104 ThreadRegistryLock l(&ctx->thread_registry);
105 new (rep) ScopedReport(ReportTypeThreadLeak);
106 rep->AddThread(leaks[i].tctx, true);
107 rep->SetCount(leaks[i].count);
108# if SANITIZER_APPLE
109 } // Close this scope to release the locks
110# endif
111 OutputReport(thr, *rep);
112
113 // Need to manually destroy this because we used placement new to allocate
114 rep->~ScopedReport();
115# if !SANITIZER_APPLE
116 }
117# endif
100118 }
101119#endif
102120}
......@@ -149,7 +167,7 @@ struct OnStartedArgs {
149167 uptr tls_size;
150168};
151169
152void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,
170void ThreadStart(ThreadState *thr, Tid tid, ThreadID os_id,
153171 ThreadType thread_type) {
154172 ctx->thread_registry.StartThread(tid, os_id, thread_type, thr);
155173 if (!thr->ignore_sync) {
......@@ -188,10 +206,14 @@ void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,
188206 }
189207#endif
190208
191#if !SANITIZER_GO
209#if !SANITIZER_GO && !SANITIZER_ANDROID
192210 // Don't imitate stack/TLS writes for the main thread,
193211 // because its initialization is synchronized with all
194212 // subsequent threads anyway.
213 // Because thr is created by MmapOrDie, the thr object
214 // is not in tls, the pointer to the thr object is in
215 // TLS_SLOT_SANITIZER slot. So skip this check on
216 // Android platform.
195217 if (tid != kMainTid) {
196218 if (stk_addr && stk_size) {
197219 const uptr pc = StackTrace::GetNextInstructionPc(
lib/libtsan/tsan_symbolize.cpp+1-1
......@@ -79,7 +79,7 @@ static void AddFrame(void *ctx, const char *function_name, const char *file,
7979 info->column = column;
8080}
8181
82SymbolizedStack *SymbolizeCode(uptr addr) {
82SymbolizedStack* SymbolizeCode(uptr addr, bool leaf) {
8383 // Check if PC comes from non-native land.
8484 if (addr & kExternalPCBit) {
8585 SymbolizedStackBuilder ssb = {nullptr, nullptr, addr};
lib/libtsan/tsan_symbolize.h+1-1
......@@ -19,7 +19,7 @@ namespace __tsan {
1919
2020void EnterSymbolizer();
2121void ExitSymbolizer();
22SymbolizedStack *SymbolizeCode(uptr addr);
22SymbolizedStack* SymbolizeCode(uptr addr, bool leaf);
2323ReportLocation *SymbolizeData(uptr addr);
2424void SymbolizeFlush();
2525
lib/libtsan/tsan_trace.h+1-1
......@@ -190,7 +190,7 @@ struct Trace {
190190 Mutex mtx;
191191 IList<TraceHeader, &TraceHeader::trace_parts, TracePart> parts;
192192 // First node non-queued into ctx->trace_part_recycle.
193 TracePart* local_head;
193 TracePart* local_head = nullptr;
194194 // Final position in the last part for finished threads.
195195 Event* final_pos = nullptr;
196196 // Number of trace parts allocated on behalf of this trace specifically.