@@ -119,9 +119,13 @@ struct Metadata {
119119#[ repr( C ) ]
120120#[ cfg_attr( target_arch = "arm" , repr( align( 8 ) ) ) ]
121121struct Abi {
122- /// Aarch64 has an ABI-exposed `dtv` field (though we don't yet implement
123- /// dynamic linking).
124- #[ cfg( any( target_arch = "aarch64" , target_arch = "arm" ) ) ]
122+ /// The ABI-exposed `canary` field.
123+ #[ cfg( any( target_arch = "aarch64" , target_arch = "arm" , target_arch = "riscv64" ) ) ]
124+ canary : usize ,
125+
126+ /// The ABI-exposed `dtv` field (though we don't yet implement dynamic
127+ /// linking).
128+ #[ cfg( any( target_arch = "aarch64" , target_arch = "arm" , target_arch = "riscv64" ) ) ]
125129 dtv : * const c_void ,
126130
127131 /// x86 and x86-64 put a copy of the thread-pointer register at the memory
@@ -130,9 +134,25 @@ struct Abi {
130134 #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
131135 this : * mut Abi ,
132136
137+ /// The ABI-exposed `dtv` field (though we don't yet implement dynamic
138+ /// linking).
139+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
140+ dtv : * const c_void ,
141+
142+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
143+ _pad : [ usize ; 3 ] ,
144+
145+ /// The ABI-exposed `canary` field.
146+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
147+ canary : usize ,
148+
133149 /// Padding to put the TLS data which follows at its known offset.
134150 #[ cfg( any( target_arch = "aarch64" , target_arch = "arm" ) ) ]
135- pad : [ usize ; 1 ] ,
151+ _pad : [ usize ; 1 ] ,
152+
153+ /// Padding to put the TLS data which follows at its known offset.
154+ #[ cfg( target_arch = "riscv64" ) ]
155+ _pad : [ usize ; 0 ] ,
136156}
137157
138158/// Information obtained from the `DT_TLS` segment of the executable.
@@ -331,15 +351,19 @@ pub(super) unsafe fn initialize_main_thread(mem: *mut c_void) {
331351 let thread_id_ptr = ( * metadata) . thread . thread_id . as_ptr ( ) ;
332352 let tid = rustix:: runtime:: set_tid_address ( thread_id_ptr. cast ( ) ) ;
333353
354+ // Initialize the canary value from the OS-provided random bytes.
355+ let random_ptr = rustix:: runtime:: random ( ) . cast :: < usize > ( ) ;
356+ let canary = random_ptr. read_unaligned ( ) ;
357+ __stack_chk_guard = canary;
358+
334359 // Initialize the thread metadata.
335360 metadata. write ( Metadata {
336361 abi : Abi {
362+ canary,
363+ dtv : null ( ) ,
337364 #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
338365 this : newtls,
339- #[ cfg( any( target_arch = "aarch64" , target_arch = "arm" ) ) ]
340- dtv : null ( ) ,
341- #[ cfg( any( target_arch = "aarch64" , target_arch = "arm" ) ) ]
342- pad : [ 0_usize ; 1 ] ,
366+ _pad : Default :: default ( ) ,
343367 } ,
344368 thread : ThreadData :: new (
345369 Some ( tid) ,
@@ -464,15 +488,17 @@ pub unsafe fn create_thread(
464488 let metadata: * mut Metadata = map. add ( header) . cast ( ) ;
465489 let newtls: * mut Abi = & mut ( * metadata) . abi ;
466490
491+ // Copy the current thread's canary to the new thread.
492+ let canary = ( * current_metadata ( ) ) . abi . canary ;
493+
467494 // Initialize the thread metadata.
468495 metadata. write ( Metadata {
469496 abi : Abi {
497+ canary,
498+ dtv : null ( ) ,
470499 #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
471500 this : newtls,
472- #[ cfg( any( target_arch = "aarch64" , target_arch = "arm" ) ) ]
473- dtv : null ( ) ,
474- #[ cfg( any( target_arch = "aarch64" , target_arch = "arm" ) ) ]
475- pad : [ 0_usize ; 1 ] ,
501+ _pad : Default :: default ( ) ,
476502 } ,
477503 thread : ThreadData :: new (
478504 None , // the real tid will be written by `clone`.
@@ -1031,6 +1057,10 @@ extern "C" fn __aeabi_read_tp() -> *mut c_void {
10311057 thread_pointer ( )
10321058}
10331059
1060+ /// Some targets use this global variable instead of the TLS `canary` field.
1061+ #[ no_mangle]
1062+ static mut __stack_chk_guard: usize = 0 ;
1063+
10341064const fn round_up ( addr : usize , boundary : usize ) -> usize {
10351065 ( addr + ( boundary - 1 ) ) & boundary. wrapping_neg ( )
10361066}
0 commit comments