min-sized-rust icon indicating copy to clipboard operation
min-sized-rust copied to clipboard

Local file path strings embedded in binary

Open ptdecker opened this issue 2 years ago • 7 comments

Hello!

I'm working through this awesome guide to reduce the size of my compiled binaries. It is making a big difference. While inspecting the result, I used strings to take a look at what strings are still in the result. I see multiple places where it appears that the resultant release binary contains file paths which are a reflection of my local file system. Also, these paths are sometimes long and thus also contributing slightly to binary size. I'd like to understand why these full paths are being included and if there is a way to suppress them.

Your help, thoughts, and ideas are much appreciated!

Here is my release compile profile:

[profile.release]
# Cf. https://github.com/johnthagen/min-sized-rust
strip = true # automatically strip symbols from the binary
opt-level = "s" # optimize for binary size
lto = true # link-time optimization enabled
codegen-units = 1 # prevent build-time parallelization
debug = false
panic = "abort"

And, here is a redacted sample of the output of strings on the resultant binary:

release/macos/aarch64/bin/foo | grep "ptdecker"

Output (redacted):

[redacted]
/Users/ptdecker/.cargo/registry/src/index.crates.io-6f17d22bba15001f/indexmap-2.1.0/src/map/core.rsBigNumber failed to deserialize: 11Broadcast is less than 4 bytes and does not include key version Keys were generated with Crypto Module Version ./Users/ptdecker/PycharmProjects/foo/fizz/src/common/secure_big_num.rsSecureBigNumber failed to deserialize:
gcd(challenge,N) != 1 for Paillier GCD Proof Challenge Generation!/Users/ptdecker/PycharmProjects/bar/[redacted]
/rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/sync/atomic.rsthere is no such thing as an acquire storethere is no such thing as an acquire-release storeinternal error: entered unreachable code: unknown state: /Users/ptdecker/.cargo/registry/src/index.crates.io-6f17d22bba15001f/want-0.3.1/src/lib.rs/Users/ptdecker/.cargo/registry/src/index.crates.io-6f17d22bba15001f/zeroize-1.6.0/src/lib.rsassertion failed: size <= isize::MAX as usize
/Users/ptdecker/PycharmProjects/foo/fizz/target/aarch64-apple-darwin/release/build/openssl-sys-f6a0d3a636f0f1e4/out/openssl-build/install/lib/engines-3
/Users/ptdecker/PycharmProjects/foo/fizz/target/aarch64-apple-darwin/release/build/openssl-sys-f6a0d3a636f0f1e4/out/openssl-build/install/lib/ossl-modules
[redacted]

Note the /Users/ptdecker/PycharmProjects/baz/foo/target... paths

ptdecker avatar Nov 06 '23 17:11 ptdecker

You may be interested in this:

  • https://github.com/rust-lang/rfcs/pull/3127#issuecomment-1546718539

Specifically -Ztrim-paths

  • https://github.com/rust-lang/cargo/pull/12625

johnthagen avatar Nov 06 '23 20:11 johnthagen

Thank you @johnthagen, I will check these out!

Also, I was looking through the Unstable Book and found these--any thoughts if they are helpful too? On quick look, looks like perhaps the -Ztrim-paths is related to these. I really appreciate you chiming in on this thread. I'll read the links you provided and close with findings if it addresses my issue.

ptdecker avatar Nov 08 '23 22:11 ptdecker

Ran with -Ztrim-paths on current nightly but the local paths are still in there. I'm probably doing something wrong with it and will keep working at it.

ptdecker avatar Nov 08 '23 23:11 ptdecker

This won't help for size, but a short term idea to help avoid leaking your personal information into the binaries would be to build in a container (for Linux builds) or some kind of generic CI system or VM for Windows/macOS such as GitHub Actions.

johnthagen avatar Nov 09 '23 12:11 johnthagen

For reproduction, there is this example (which began the discussion that led to -Z trim-paths):

[dependencies]
rand = "0.8.0"
use rand::prelude::*;
    
fn main() {
    let r: f64 = rand::thread_rng().gen();
    println!("{}", r);
}

Then with either the mentioned -Z trim-paths or RUSTFLAGS -Z location-detail=none the home user is not present in the strings output:

$ cargo +nightly build --release -Z trim-paths
$ RUSTFLAGS="-Z location-detail=none" cargo +nightly build --release
  • I confirmed it did contain my user home path without either of those options (with or without your Cargo.toml release additons).
  • I built this reproduction:
    • With a fresh project created via cargo init + applying the above change snippets.
    • With the current nightly for Rust.
    • On Windows WSL2 x86_64 with the x86_64-unknown-linux-gnu target & toolchain.

Perhaps you can verify the above, and then try identify what is being done differently for those not to work. Make sure you're not building from any cache which may already have those paths too?

There is also this issue which notes that RUSTFLAGS will apply differently when an explicit --target is set. I could be misunderstanding that though, may only be relevant when using -C target-feature to override a target default. Still it highlights a gotcha where config compiled differently (the fix for the user was to provide the explicit --target).

TL;DR

Maybe try -Z location-detail=none (RUSTFLAG env, not cargo option), since it seems to achieve the same? (at least in the reproduction example, I assume it's a more aggressive approach with other side-effects)

polarathene avatar Nov 22 '23 02:11 polarathene

I am able to get rid of all path and dependencies information by adding trim-paths = "all" to [profile.release]. Now the official RFC doc mentioned this option.

lihe07 avatar Jan 21 '24 12:01 lihe07

From https://rust-lang.github.io/rfcs/3127-trim-paths.html#cargo:

It is defaulted to none for debug profiles, and object for release profiles

The default release profile setting (object) sanitises only the paths in emitted executable or library files. It always affects paths from macros such as panic messages, and in debug information only if they will be embedded together with the binary (the default on platforms with ELF binaries, such as Linux and windows-gnu), but will not touch them if they are in separate files (the default on Windows MSVC and macOS). But the paths to these separate files are sanitised.

Reading the docs, it seems like this default for release profile should resolve most practical issues related to privacy. So when this goes stable, trimming paths should just work for everyone. Also seems like if you are using nightly, you can already get this behavior by default.

For reference, as of Rust 1.75.0, this is still a nightly-only feature.

johnthagen avatar Jan 21 '24 13:01 johnthagen