Skip to content

Commit f0eb671

Browse files
committed
rust: validate glibc symbol versions
We want to ensure that we only reference glibc versions older than a threshold.
1 parent fc3be4a commit f0eb671

File tree

3 files changed

+61
-2
lines changed

3 files changed

+61
-2
lines changed

Cargo.lock

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,10 @@ goblin = "0.3"
1111
lazy_static = "1.4"
1212
scroll = "0.10"
1313
tar = "0.4"
14+
version-compare = "0.0.11"
1415
zstd = "0.6"
16+
17+
[dependencies.tugger-binary-analysis]
18+
version = "0.1.0-pre"
19+
git = "https://github.com/indygreg/PyOxidizer.git"
20+
rev = "e86b2f46ed6b449bdb912900b0ac83576ad5ebe9"

src/main.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use {
1414
std::{
1515
convert::TryInto,
1616
io::Read,
17+
ops::Deref,
1718
path::{Path, PathBuf},
1819
},
1920
};
@@ -85,6 +86,8 @@ const PE_ALLOWED_LIBRARIES: &[&str] = &[
8586
];
8687

8788
lazy_static! {
89+
static ref GLIBC_MAX_VERSION: version_compare::Version<'static> =
90+
version_compare::Version::from("2.19").unwrap();
8891
static ref MACHO_ALLOWED_DYLIBS: Vec<MachOAllowedDylib> = {
8992
[
9093
MachOAllowedDylib {
@@ -174,7 +177,7 @@ lazy_static! {
174177
};
175178
}
176179

177-
fn validate_elf(path: &Path, elf: &goblin::elf::Elf) -> Result<Vec<String>> {
180+
fn validate_elf(path: &Path, elf: &goblin::elf::Elf, bytes: &[u8]) -> Result<Vec<String>> {
178181
let mut errors = vec![];
179182

180183
for lib in &elf.libraries {
@@ -183,6 +186,30 @@ fn validate_elf(path: &Path, elf: &goblin::elf::Elf) -> Result<Vec<String>> {
183186
}
184187
}
185188

189+
let mut undefined_symbols = tugger_binary_analysis::find_undefined_elf_symbols(&bytes, elf);
190+
undefined_symbols.sort();
191+
192+
for symbol in undefined_symbols {
193+
if let Some(version) = &symbol.version {
194+
let parts: Vec<&str> = version.splitn(2, '_').collect();
195+
196+
if parts.len() == 2 {
197+
if parts[0] == "GLIBC" {
198+
let v =
199+
version_compare::Version::from(parts[1]).expect("unable to parse version");
200+
201+
if &v > GLIBC_MAX_VERSION.deref() {
202+
errors.push(format!(
203+
"{} references too new glibc symbol {:?}",
204+
path.display(),
205+
symbol
206+
))
207+
}
208+
}
209+
}
210+
}
211+
}
212+
186213
Ok(errors)
187214
}
188215

@@ -253,7 +280,7 @@ fn validate_distribution(dist_path: &Path) -> Result<Vec<String>> {
253280
if let Ok(object) = goblin::Object::parse(&data) {
254281
match object {
255282
goblin::Object::Elf(elf) => {
256-
errors.extend(validate_elf(path.as_ref(), &elf)?);
283+
errors.extend(validate_elf(path.as_ref(), &elf, &data)?);
257284
}
258285
goblin::Object::Mach(mach) => match mach {
259286
goblin::mach::Mach::Binary(macho) => {

0 commit comments

Comments
 (0)