9
9
normalize_path:: NormalizePath ,
10
10
object:: {
11
11
elf:: {
12
- FileHeader32 , FileHeader64 , ET_DYN , ET_EXEC , STB_GLOBAL , STB_WEAK , STV_DEFAULT ,
12
+ FileHeader32 , FileHeader64 , ET_DYN , ET_EXEC , SHN_UNDEF , STB_GLOBAL , STB_WEAK , STV_DEFAULT ,
13
13
STV_HIDDEN ,
14
14
} ,
15
15
macho:: { MachHeader32 , MachHeader64 , MH_OBJECT , MH_TWOLEVEL } ,
@@ -265,6 +265,25 @@ static ELF_ALLOWED_LIBRARIES_BY_TRIPLE: Lazy<HashMap<&'static str, Vec<&'static
265
265
. collect ( )
266
266
} ) ;
267
267
268
+ static ELF_ALLOWED_LIBRARIES_BY_MODULE : Lazy < HashMap < & ' static str , Vec < & ' static str > > > =
269
+ Lazy :: new ( || {
270
+ [
271
+ (
272
+ // libcrypt is provided by the system, but only on older distros.
273
+ "_crypt" ,
274
+ vec ! [ "libcrypt.so.1" ] ,
275
+ ) ,
276
+ (
277
+ // libtcl and libtk are shipped in our distribution.
278
+ "_tkinter" ,
279
+ vec ! [ "libtcl8.6.so" , "libtk8.6.so" ] ,
280
+ ) ,
281
+ ]
282
+ . iter ( )
283
+ . cloned ( )
284
+ . collect ( )
285
+ } ) ;
286
+
268
287
static DARWIN_ALLOWED_DYLIBS : Lazy < Vec < MachOAllowedDylib > > = Lazy :: new ( || {
269
288
[
270
289
MachOAllowedDylib {
@@ -501,6 +520,29 @@ static IOS_ALLOWED_DYLIBS: Lazy<Vec<MachOAllowedDylib>> = Lazy::new(|| {
501
520
. to_vec ( )
502
521
} ) ;
503
522
523
+ static ALLOWED_DYLIBS_BY_MODULE : Lazy < HashMap < & ' static str , Vec < MachOAllowedDylib > > > =
524
+ Lazy :: new ( || {
525
+ [ (
526
+ // libtcl and libtk are shipped in our distribution.
527
+ "_tkinter" ,
528
+ vec ! [
529
+ MachOAllowedDylib {
530
+ name: "libtcl8.6.dylib" . to_string( ) ,
531
+ max_compatibility_version: "1.0.0" . try_into( ) . unwrap( ) ,
532
+ required: true ,
533
+ } ,
534
+ MachOAllowedDylib {
535
+ name: "libtk8.6.dylib" . to_string( ) ,
536
+ max_compatibility_version: "1.0.0" . try_into( ) . unwrap( ) ,
537
+ required: true ,
538
+ } ,
539
+ ] ,
540
+ ) ]
541
+ . iter ( )
542
+ . cloned ( )
543
+ . collect ( )
544
+ } ) ;
545
+
504
546
static PLATFORM_TAG_BY_TRIPLE : Lazy < HashMap < & ' static str , & ' static str > > = Lazy :: new ( || {
505
547
[
506
548
( "aarch64-apple-darwin" , "macosx-11.0-arm64" ) ,
@@ -591,6 +633,11 @@ const DEPENDENCY_PACKAGE_SYMBOLS: &[&str] = &[
591
633
// liblzma
592
634
"lzma_index_init" ,
593
635
"lzma_stream_encoder" ,
636
+ ] ;
637
+
638
+ // TODO(geofft): Conditionally prohibit these exported symbols
639
+ // everywhere except libtcl and libtk. This should be a hashmap
640
+ const _DEPENDENCY_PACKAGE_SYMBOLS_BUNDLED: & [ & str ] = & [
594
641
// tcl
595
642
"Tcl_Alloc" ,
596
643
"Tcl_ChannelName" ,
@@ -967,11 +1014,13 @@ fn validate_elf<Elf: FileHeader<Endian = Endianness>>(
967
1014
allowed_libraries. push ( "libc.so" . to_string ( ) ) ;
968
1015
}
969
1016
970
- // Allow the _crypt extension module - and only it - to link against libcrypt,
971
- // which is no longer universally present in Linux distros .
1017
+ // Allow certain extension modules to link against shared libraries
1018
+ // (either from the system or from our distribution) .
972
1019
if let Some ( filename) = path. file_name ( ) {
973
- if filename. to_string_lossy ( ) . starts_with ( "_crypt" ) {
974
- allowed_libraries. push ( "libcrypt.so.1" . to_string ( ) ) ;
1020
+ if let Some ( ( module, _) ) = filename. to_string_lossy ( ) . split_once ( ".cpython-" ) {
1021
+ if let Some ( extra) = ELF_ALLOWED_LIBRARIES_BY_MODULE . get ( module) {
1022
+ allowed_libraries. extend ( extra. iter ( ) . map ( |x| x. to_string ( ) ) ) ;
1023
+ }
975
1024
}
976
1025
}
977
1026
@@ -1109,6 +1158,7 @@ fn validate_elf<Elf: FileHeader<Endian = Endianness>>(
1109
1158
// to prevent them from being exported.
1110
1159
if DEPENDENCY_PACKAGE_SYMBOLS . contains ( & name. as_ref ( ) )
1111
1160
&& matches ! ( symbol. st_bind( ) , STB_GLOBAL | STB_WEAK )
1161
+ && symbol. st_shndx ( endian) != SHN_UNDEF
1112
1162
&& symbol. st_visibility ( ) != STV_HIDDEN
1113
1163
{
1114
1164
context. errors . push ( format ! (
@@ -1124,6 +1174,7 @@ fn validate_elf<Elf: FileHeader<Endian = Endianness>>(
1124
1174
if filename. starts_with ( "libpython" )
1125
1175
&& filename. ends_with ( ".so.1.0" )
1126
1176
&& matches ! ( symbol. st_bind( ) , STB_GLOBAL | STB_WEAK )
1177
+ && symbol. st_shndx ( endian) != SHN_UNDEF
1127
1178
&& symbol. st_visibility ( ) == STV_DEFAULT
1128
1179
{
1129
1180
context. libpython_exported_symbols . insert ( name. to_string ( ) ) ;
@@ -1225,7 +1276,16 @@ fn validate_macho<Mach: MachHeader<Endian = Endianness>>(
1225
1276
1226
1277
dylib_names. push ( lib. clone ( ) ) ;
1227
1278
1228
- let allowed = allowed_dylibs_for_triple ( target_triple) ;
1279
+ let mut allowed = allowed_dylibs_for_triple ( target_triple) ;
1280
+ // Allow certain extension modules to link against shared libraries
1281
+ // (either from the system or from our distribution).
1282
+ if let Some ( filename) = path. file_name ( ) {
1283
+ if let Some ( ( module, _) ) = filename. to_string_lossy ( ) . split_once ( ".cpython-" ) {
1284
+ if let Some ( extra) = ALLOWED_DYLIBS_BY_MODULE . get ( module) {
1285
+ allowed. extend ( extra. clone ( ) ) ;
1286
+ }
1287
+ }
1288
+ }
1229
1289
1230
1290
if let Some ( entry) = allowed. iter ( ) . find ( |l| l. name == lib) {
1231
1291
let load_version =
0 commit comments