Skip to content

Implement old version fallback using dlsym #223

Open
@madsmtm

Description

@madsmtm

rustls-platform-verifier (nowadays used in major Rust projects like Rustup) uses security-framework, and enables the "OSX_10_14" Cargo feature.

As such, trying to run rustup update on a machine with macOS 10.12 installed (which the Rust project otherwise still supports) results in the following dynamic linker error:

info: syncing channel updates for 'stable-x86_64-apple-darwin'
dyld: lazy symbol binding failed: Symbol not found: _SecTrustEvaluateWithError
  Referenced from: /Users/madsmtm/.cargo/bin/rustup
  Expected in: /System/Library/Frameworks/Security.framework/Versions/A/Security

dyld: Symbol not found: _SecTrustEvaluateWithError
  Referenced from: /Users/madsmtm/.cargo/bin/rustup
  Expected in: /System/Library/Frameworks/Security.framework/Versions/A/Security

Abort trap: 6

And trying to compile it manually results in a static linker error:

error: linking with `cc` failed: exit status: 1
  |
  = note: "cc" "$WORKSPACE/*.o" "$WORKSPACE/*.rlib" "-framework" "Security" "-liconv" "-framework" "CoreFoundation" "-lSystem" "-lc" "-lm" "-arch" "x86_64" "-mmacosx-version-min=10.12.0" "-o" "$WORKSPACE/target/debug/deps/rustls_platform_verifier-f3c84624becba9b5" "-Wl,-dead_strip" "-nodefaultlibs"
  = note: Undefined symbols for architecture x86_64:
            "_SecTrustEvaluateWithError", referenced from:
                security_framework::trust::SecTrust::evaluate_with_error::hb6ce8f9ed18e6bcb in libsecurity_framework-063e6ee960d31664.rlib(security_framework-063e6ee960d31664.security_framework.d276614c73a19b26-cgu.10.rcgu.o)
          ld: symbol(s) not found for architecture x86_64
          clang: error: linker command failed with exit code 1 (use -v to see invocation)

error: could not compile `rustls-platform-verifier` (lib test) due to 1 previous error

This could of course be "fixed" in rustls-platform-verifier by simply not enabling the feature at all, but there's (probably) a reason why they've chosen to do so. Ideally, we should be able to use SecTrustEvaluateWithError when available, and only need to fall back to SecTrustEvaluate when not available.

Weak linking offers such a mechanism, though it has been unstable for years with difficult blockers, so another solution would be to look the symbol up dynamically using dlsym. Something like the following would work:

let fnptr = dlsym(RTLD_DEFAULT, c"SecTrustEvaluateWithError".as_ptr());
let fnptr = mem::transmute<*const c_void, Option<unsafe extern "C" fn(SecTrustRef, *mut CFErrorRef) -> bool>>();
if let Some(fnptr) = fnptr {
    // SecTrustEvaluateWithError available
    fnptr(...)
} else {
    // Not available, fall back to SecTrustEvaluate
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions