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

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.