Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions .github/workflows/prefix.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
name: prefix

on:
pull_request:
branches:
- master
push:
branches:
- master

jobs:
prefix-symbols:
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
bin: ""
test: true
custom_env: {}
- target: aarch64-unknown-linux-gnu
os: ubuntu-latest
bin: ""
test: false
apt_packages: crossbuild-essential-arm64 binutils-multiarch
custom_env:
CC_aarch64_unknown_linux_gnu: aarch64-linux-gnu-gcc
CXX_aarch64_unknown_linux_gnu: aarch64-linux-gnu-g++
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-g++
- target: armv7-linux-androideabi
os: ubuntu-latest
bin: ndk
test: false
custom_env: {}
- target: aarch64-linux-android
os: ubuntu-latest
bin: ndk
test: false
custom_env: {}
- target: x86_64-linux-android
os: ubuntu-latest
bin: ndk
test: false
custom_env: {}
- target: i686-linux-android
os: ubuntu-latest
bin: ndk
test: false
custom_env: {}
defaults:
run:
working-directory: test-project
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Create test project
working-directory: .
run: |
cargo init test-project
cd test-project
cargo add boring-sys --path ../boring-sys/
cargo add openssl-sys -F vendored
echo "fn main() {boring_sys::init(); openssl_sys::init();}" > src/main.rs
- name: Install Rust toolchain
shell: bash
run: rustup target add ${{ matrix.target }}
- name: Install target-specific APT dependencies
if: matrix.apt_packages != ''
run: sudo apt update && sudo apt install -y ${{ matrix.apt_packages }}
- name: Install cargo-ndk
if: contains(matrix.target, 'android')
run: |
cargo install cargo-ndk
# Openssl fix for i686: https://github.com/rust-openssl/rust-openssl/issues/2163#issuecomment-2692363343
echo "ANDROID_NDK=$ANDROID_NDK_LATEST_HOME" >> $GITHUB_ENV
echo "ANDROID_NDK_HOME=$ANDROID_NDK_LATEST_HOME" >> $GITHUB_ENV
echo "ANDROID_NDK_ROOT=$ANDROID_NDK_LATEST_HOME" >> $GITHUB_ENV
echo "CARGO_TARGET_I686_LINUX_ANDROID_RUSTFLAGS=-C link-arg=-lclang_rt.builtins-i686-android -C link-arg=-L${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/21/lib/linux/" >> $GITHUB_ENV
- name: Build without prefixing
env: ${{ matrix.custom_env }}
shell: bash
run: |
RC=0
cargo ${{ matrix.bin }} build --target ${{ matrix.target }} >logs 2>&1 || RC=$?
if [[ $RC == 0 || (! $(cat logs | grep "lld: error: duplicate symbol") && ! $(cat logs | grep "multiple definition of")) ]]; then
cat logs
echo "Build finished without duplicate symbols: $RC"
exit 1
fi
cat logs
echo "Failed as expected: $RC"
- name: Add prefix-symbols feature
shell: bash
run: cargo add boring-sys --path ../boring-sys/ -F prefix-symbols
- name: Build with prefixing
env: ${{ matrix.custom_env }}
shell: bash
run: cargo ${{ matrix.bin }} build --target ${{ matrix.target }}
- name: Check if the is no runtime failures
if: matrix.test == true
shell: bash
run: cargo ${{ matrix.bin }} run --target ${{ matrix.target }}
4 changes: 4 additions & 0 deletions boring-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ rpk = []
# `BORING_BSSL{,_FIPS}_SOURCE_PATH`.
underscore-wildcards = []

# Add a prefix to all symbols in libcrypto and libssl to prevent conflicts
# with other OpenSSL or BoringSSL versions that might be linked in the same process.
prefix-symbols = []

[build-dependencies]
bindgen = { workspace = true }
cmake = { workspace = true }
Expand Down
3 changes: 3 additions & 0 deletions boring-sys/build/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub(crate) struct Features {
pub(crate) fips: bool,
pub(crate) rpk: bool,
pub(crate) underscore_wildcards: bool,
pub(crate) prefix_symbols: bool,
}

pub(crate) struct Env {
Expand Down Expand Up @@ -105,11 +106,13 @@ impl Features {
let fips = env::var_os("CARGO_FEATURE_FIPS").is_some();
let rpk = env::var_os("CARGO_FEATURE_RPK").is_some();
let underscore_wildcards = env::var_os("CARGO_FEATURE_UNDERSCORE_WILDCARDS").is_some();
let prefix_symbols = env::var_os("CARGO_FEATURE_PREFIX_SYMBOLS").is_some();

Self {
fips,
rpk,
underscore_wildcards,
prefix_symbols,
}
}

Expand Down
19 changes: 19 additions & 0 deletions boring-sys/build/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use core::panic;
use fslock::LockFile;
use std::env;
use std::ffi::OsString;
Expand All @@ -9,8 +10,10 @@ use std::process::{Command, Output};
use std::sync::OnceLock;

use crate::config::Config;
use crate::prefix::{prefix_symbols, PrefixCallback};

mod config;
mod prefix;

fn should_use_cmake_cross_compilation(config: &Config) -> bool {
if config.host == config.target {
Expand Down Expand Up @@ -543,6 +546,10 @@ fn built_boring_source_path(config: &Config) -> &PathBuf {
.define("FIPS", "1");
}

if config.features.prefix_symbols {
cfg.define("CMAKE_POSITION_INDEPENDENT_CODE", "ON");
}

cfg.build_target("ssl").build();
cfg.build_target("crypto").build()
})
Expand Down Expand Up @@ -570,6 +577,14 @@ fn main() {
if !config.env.docs_rs {
emit_link_directives(&config);
}
if config.features.prefix_symbols
&& ["macos", "ios", "windows"].contains(&config.target_os.as_str())
{
panic!("The `prefix_symbols` feature is not supported on macOS/iOS or windows targets.");
}
if config.features.prefix_symbols {
prefix_symbols(&config);
}
generate_bindings(&config);
}

Expand Down Expand Up @@ -664,6 +679,10 @@ fn generate_bindings(config: &Config) {
.clang_arg(sysroot.display().to_string());
}

if config.features.prefix_symbols {
builder = builder.parse_callbacks(Box::new(PrefixCallback));
}

let headers = [
"aes.h",
"asn1_mac.h",
Expand Down
89 changes: 89 additions & 0 deletions boring-sys/build/prefix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
use crate::{config::Config, pick_best_android_ndk_toolchain, run_command};
use std::{fs, io::Write, path::PathBuf, process::Command};

// The prefix to add to all symbols
// Using crate name to avoid collisions with other projects
const PREFIX: &str = env!("CARGO_CRATE_NAME");

// Callback to add a `link_name` macro with the prefix to all generated bindings
#[derive(Debug)]
pub struct PrefixCallback;

impl bindgen::callbacks::ParseCallbacks for PrefixCallback {
fn generated_link_name_override(
&self,
item_info: bindgen::callbacks::ItemInfo<'_>,
) -> Option<String> {
Some(format!("{PREFIX}_{}", item_info.name))
}
}

fn android_toolchain(config: &Config) -> PathBuf {
let mut android_bin_path = config
.env
.android_ndk_home
.clone()
.expect("Please set ANDROID_NDK_HOME for Android build");
android_bin_path.extend(["toolchains", "llvm", "prebuilt"]);
android_bin_path.push(pick_best_android_ndk_toolchain(&android_bin_path).unwrap());
android_bin_path.push("bin");
android_bin_path
}

pub fn prefix_symbols(config: &Config) {
// List static libraries to prefix symbols in
let static_libs: Vec<PathBuf> = [
config.out_dir.join("build"),
config.out_dir.join("build").join("ssl"),
config.out_dir.join("build").join("crypto"),
]
.iter()
.flat_map(|dir| {
["libssl.a", "libcrypto.a"]
.into_iter()
.map(move |file| PathBuf::from(dir).join(file))
})
.filter(|p| p.exists())
.collect();

// Use `nm` to list symbols in these static libraries
let nm = match &*config.target_os {
"android" => android_toolchain(config).join("llvm-nm"),
_ => PathBuf::from("nm"),
};
let out = run_command(Command::new(nm).args(&static_libs)).unwrap();
let mut redefine_syms: Vec<String> = String::from_utf8_lossy(&out.stdout)
.lines()
.filter(|l| {
[" T ", " D ", " B ", " C ", " R ", " W "]
.iter()
.any(|s| l.contains(s))
})
.filter_map(|l| l.split_whitespace().nth(2).map(|s| s.to_string()))
.filter(|l| !l.starts_with("_"))
.map(|l| format!("{l} {PREFIX}_{l}"))
.collect();
redefine_syms.sort();
redefine_syms.dedup();

let redefine_syms_path = config.out_dir.join("redefine_syms.txt");
let mut f = fs::File::create(&redefine_syms_path).unwrap();
for sym in &redefine_syms {
writeln!(f, "{sym}").unwrap();
}
f.flush().unwrap();

// Use `objcopy` to prefix symbols in these static libraries
let objcopy = match &*config.target_os {
"android" => android_toolchain(config).join("llvm-objcopy"),
_ => PathBuf::from("objcopy"),
};
for static_lib in &static_libs {
run_command(
Command::new(&objcopy)
.arg(format!("--redefine-syms={}", redefine_syms_path.display()))
.arg(static_lib),
)
.unwrap();
}
}
4 changes: 4 additions & 0 deletions boring/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ rpk = ["boring-sys/rpk"]
# `BORING_BSSL{,_FIPS}_ASSUME_PATCHED`.
underscore-wildcards = ["boring-sys/underscore-wildcards"]

# Add a prefix to all symbols in libcrypto and libssl to prevent conflicts
# with other OpenSSL or BoringSSL versions that might be linked in the same process.
prefix-symbols = ["boring-sys/prefix-symbols"]

[dependencies]
bitflags = { workspace = true }
foreign-types = { workspace = true }
Expand Down