99 normalize_path:: NormalizePath ,
1010 object:: {
1111 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 ,
1313 STV_HIDDEN ,
1414 } ,
1515 macho:: { MachHeader32 , MachHeader64 , MH_OBJECT , MH_TWOLEVEL } ,
@@ -265,6 +265,25 @@ static ELF_ALLOWED_LIBRARIES_BY_TRIPLE: Lazy<HashMap<&'static str, Vec<&'static
265265 . collect ( )
266266 } ) ;
267267
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+
268287static DARWIN_ALLOWED_DYLIBS : Lazy < Vec < MachOAllowedDylib > > = Lazy :: new ( || {
269288 [
270289 MachOAllowedDylib {
@@ -501,6 +520,30 @@ static IOS_ALLOWED_DYLIBS: Lazy<Vec<MachOAllowedDylib>> = Lazy::new(|| {
501520 . to_vec ( )
502521} ) ;
503522
523+ static ALLOWED_DYLIBS_BY_MODULE : Lazy < HashMap < & ' static str , Vec < MachOAllowedDylib > > > =
524+ Lazy :: new ( || {
525+ [
526+ (
527+ // libtcl and libtk are shipped in our distribution.
528+ "_tkinter" ,
529+ vec ! [
530+ MachOAllowedDylib {
531+ name: "libtcl8.6.dylib" . to_string( ) ,
532+ max_compatibility_version: "1.0.0" . try_into( ) . unwrap( ) ,
533+ required: true ,
534+ } ,
535+ MachOAllowedDylib {
536+ name: "libtk8.6.dylib" . to_string( ) ,
537+ max_compatibility_version: "1.0.0" . try_into( ) . unwrap( ) ,
538+ required: true ,
539+ } ] ,
540+ ) ,
541+ ]
542+ . iter ( )
543+ . cloned ( )
544+ . collect ( )
545+ } ) ;
546+
504547static PLATFORM_TAG_BY_TRIPLE : Lazy < HashMap < & ' static str , & ' static str > > = Lazy :: new ( || {
505548 [
506549 ( "aarch64-apple-darwin" , "macosx-11.0-arm64" ) ,
@@ -591,6 +634,11 @@ const DEPENDENCY_PACKAGE_SYMBOLS: &[&str] = &[
591634 // liblzma
592635 "lzma_index_init" ,
593636 "lzma_stream_encoder" ,
637+ ] ;
638+
639+ // TODO(geofft): Conditionally prohibit these exported symbols
640+ // everywhere except libtcl and libtk. This should be a hashmap
641+ const _DEPENDENCY_PACKAGE_SYMBOLS_BUNDLED: & [ & str ] = & [
594642 // tcl
595643 "Tcl_Alloc" ,
596644 "Tcl_ChannelName" ,
@@ -967,12 +1015,13 @@ fn validate_elf<Elf: FileHeader<Endian = Endianness>>(
9671015 allowed_libraries. push ( "libc.so" . to_string ( ) ) ;
9681016 }
9691017
970- // Allow the _crypt extension module - and only it - to link against libcrypt,
971- // which is no longer universally present in Linux distros.
972- 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 ( ) ) ;
975- }
1018+ // Allow certain extension modules to link against shared libraries
1019+ // (either from the system or from our distribution).
1020+ if let Some ( filename) = path. file_name ( )
1021+ && let Some ( ( module, _) ) = filename. to_string_lossy ( ) . split_once ( ".cpython-" )
1022+ && let Some ( extra) = ELF_ALLOWED_LIBRARIES_BY_MODULE . get ( module)
1023+ {
1024+ allowed_libraries. extend ( extra. iter ( ) . map ( |x| x. to_string ( ) ) ) ;
9761025 }
9771026
9781027 let wanted_glibc_max_version = GLIBC_MAX_VERSION_BY_TRIPLE
@@ -1109,6 +1158,7 @@ fn validate_elf<Elf: FileHeader<Endian = Endianness>>(
11091158 // to prevent them from being exported.
11101159 if DEPENDENCY_PACKAGE_SYMBOLS . contains ( & name. as_ref ( ) )
11111160 && matches ! ( symbol. st_bind( ) , STB_GLOBAL | STB_WEAK )
1161+ && symbol. st_shndx ( endian) != SHN_UNDEF
11121162 && symbol. st_visibility ( ) != STV_HIDDEN
11131163 {
11141164 context. errors . push ( format ! (
@@ -1124,6 +1174,7 @@ fn validate_elf<Elf: FileHeader<Endian = Endianness>>(
11241174 if filename. starts_with ( "libpython" )
11251175 && filename. ends_with ( ".so.1.0" )
11261176 && matches ! ( symbol. st_bind( ) , STB_GLOBAL | STB_WEAK )
1177+ && symbol. st_shndx ( endian) != SHN_UNDEF
11271178 && symbol. st_visibility ( ) == STV_DEFAULT
11281179 {
11291180 context. libpython_exported_symbols . insert ( name. to_string ( ) ) ;
@@ -1225,7 +1276,15 @@ fn validate_macho<Mach: MachHeader<Endian = Endianness>>(
12251276
12261277 dylib_names. push ( lib. clone ( ) ) ;
12271278
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+ && let Some ( ( module, _) ) = filename. to_string_lossy ( ) . split_once ( ".cpython-" )
1284+ && let Some ( extra) = ALLOWED_DYLIBS_BY_MODULE . get ( module)
1285+ {
1286+ allowed. extend ( extra. clone ( ) ) ;
1287+ }
12291288
12301289 if let Some ( entry) = allowed. iter ( ) . find ( |l| l. name == lib) {
12311290 let load_version =
0 commit comments