Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
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/BoringSSL versions 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
13 changes: 13 additions & 0 deletions boring-sys/build/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ use std::process::{Command, Output};
use std::sync::OnceLock;

use crate::config::Config;
use crate::prefix::{apply_symbol_prefixes, SymbolPrefixCallbacks};

mod config;
mod prefix;

fn should_use_cmake_cross_compilation(config: &Config) -> bool {
if config.host == config.target {
Expand Down Expand Up @@ -543,6 +545,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 +576,9 @@ fn main() {
if !config.env.docs_rs {
emit_link_directives(&config);
}
if config.features.prefix_symbols {
apply_symbol_prefixes(&config);
}
generate_bindings(&config);
}

Expand Down Expand Up @@ -658,6 +667,10 @@ fn generate_bindings(config: &Config) {
.clang_arg("-I")
.clang_arg(include_path.display().to_string());

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

if let Some(sysroot) = &config.env.sysroot {
builder = builder
.clang_arg("--sysroot")
Expand Down
91 changes: 91 additions & 0 deletions boring-sys/build/prefix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use crate::{config::Config, run_command};
use std::{fs, io::Write, path::PathBuf, process::Command};

/// Prefix applied to all BoringSSL symbols so they don't collide with OpenSSL.
///
const SYMBOL_PREFIX: &str = "BSSL";

/// Bindgen callback that rewrites link names to use the prefixed symbol.
///
/// C symbol `SSL_new` → Rust binding `#[link_name = "BSSL_SSL_new"]`.
#[derive(Debug)]
pub struct SymbolPrefixCallbacks;

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

/// Rewrite all global symbols in libssl.a/libcrypto.a to use the S2N_BSSL_ prefix.
///
/// This runs `nm` to list symbols and `objcopy --redefine-syms` to edit the archives
/// in-place, so they can safely coexist with other {libssl,libcrypto} in the process.
pub fn apply_symbol_prefixes(config: &Config) {
// CMake output directories where libssl.a/libcrypto.a are expected.
let static_lib_dirs = [
config.out_dir.join("build"),
config.out_dir.join("build").join("ssl"),
config.out_dir.join("build").join("crypto"),
];

let static_libs: Vec<PathBuf> = static_lib_dirs
.iter()
.flat_map(|dir| {
["libssl.a", "libcrypto.a"]
.into_iter()
.map(move |file| dir.join(file))
})
.filter(|path| path.exists())
.collect();

if static_libs.is_empty() {
eprintln!("warning: no libssl.a/libcrypto.a archives found to prefix");
return;
}

// 1. Use `nm` to list global symbols in the archives.
let nm_output = run_command(Command::new("nm").args(&static_libs))
.expect("failed to run `nm` on BoringSSL archives");

let mut mappings: Vec<String> = String::from_utf8_lossy(&nm_output.stdout)
.lines()
// Keep only global symbol types we care about.
.filter(|line| {
[" T ", " D ", " B ", " C ", " R ", " W "]
.iter()
.any(|marker| line.contains(marker))
})
// Symbol name is usually the 3rd column.
.filter_map(|line| line.split_whitespace().nth(2).map(str::to_owned))
// Skip leading-underscore internals.
.filter(|sym| !sym.starts_with('_'))
// Compose `old new` mapping line: `sym S2N_BSSL_sym`.
.map(|sym| format!("{sym} {SYMBOL_PREFIX}_{sym}"))
.collect();

mappings.sort();
mappings.dedup();

let mapping_file = config.out_dir.join("redefine_syms.txt");
let mut f = fs::File::create(&mapping_file)
.expect("failed to create redefine_syms.txt for symbol prefixing");

for mapping in &mappings {
writeln!(f, "{mapping}").expect("failed to write symbol mapping");
}
f.flush().expect("failed to flush symbol mapping file");

// 2. Use `objcopy` to apply the mapping to each archive in-place.
for static_lib in &static_libs {
run_command(
Command::new("objcopy")
.arg(format!("--redefine-syms={}", mapping_file.display()))
.arg(static_lib),
)
.expect("failed to run `objcopy` to redefine symbols");
}
}
2 changes: 2 additions & 0 deletions boring/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ rpk = ["boring-sys/rpk"]
# feature set can be provided by setting `BORING_BSSL{,_FIPS}_SOURCE_PATH` and
# `BORING_BSSL{,_FIPS}_ASSUME_PATCHED`.
underscore-wildcards = ["boring-sys/underscore-wildcards"]
# Enable symbol prefixing in the underlying BoringSSL build (for s2n tests).
prefix-symbols = ["boring-sys/prefix-symbols"]

[dependencies]
bitflags = { workspace = true }
Expand Down