Seeing something wierd disconnect with env::var Vs env::vars()

This is a LD_PRELOAD situation, my library gets run and this is in the constructor portion of the library. In the time line of 3 lines I see a difference between these 2 commands.
Dumping env::vars_os() and env::vars(), both show the environment variable "WISK_WSROOT".
The very next line does env::var("WISK_WSROOT") and errors out as not found. Cannot figure out why.
Its still the constructor, so I think it is single threaded at this point. And I can reproduce this at will

        debug(format_args!("Just before Environment: {:?}\n", env::vars_os().map(|(x,y)| x.to_str().unwrap().to_owned()).collect::<Vec<String>>()));
        debug(format_args!("Just before Environment: {:?}\n", env::vars().map(|(x,y)| x).collect::<Vec<String>>()));
        debug(format_args!("Get Operation: {:?}\n", env::var("WISK_WSROOT").unwrap()));

Output:
Just before Environment: ["LD_PRELOAD", "USER", "_", "WISK_CONFIG", "WISK_WSROOT", "TERM", "HOME", "WISK_TRACK", "PATH", "SHLVL", "WISK_TRACE", "WISK_PUUID", "PWD", "RUST_BACKTRACE"]
Just before Environment: ["LD_PRELOAD", "USER", "_", "WISK_CONFIG", "WISK_WSROOT", "TERM", "HOME", "WISK_TRACK", "PATH", "SHLVL", "WISK_TRACE", "WISK_PUUID", "PWD", "RUST_BACKTRACE"]
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: NotPresent', src/tracker.rs:143:77
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fatal runtime error: failed to initiate panic, error 5

I've even dropped into GDB and I see it happen.
I've got the data from vars into a hashmap and indexed into it and that works too.

let map: HashMap<String,String> = env::vars().collect();
debug(format_args!("Get Hashmap Operation: {:?}\n", map["WISK_WSROOT"]));

Questions:

  1. Can tell me what I am doing wrong here?
  2. Ay ideas on how to debug and root cause this.

Does libc::getenv see the var?

env::var just wraps getenv: https://github.com/rust-lang/rust/blob/95b4a4f0eee935f9e0c80b0ceef34866bcb72ca3/library/std/src/sys/unix/os.rs#L538-L552

1 Like

vars reads environ when constructed.
I would guess your preload is hijacking getenv

@jonh
my preload does not hijack getenv.

@kornel
One observation is that this happens only when the main program being intercepted is bash.
And in this case not when Bash starts up, but when bash does a exec of another program

libc::getenv also returns NULL.
So my guess env:vars reads from environ variable, while var libc::get and bash does its own getenv implementation and maintains its own environmet different frrom environ