Page MenuHomePhabricator

Issue with Symbolic Links
Closed, ResolvedPublic

Description

The uwtwrapper script does not handle symlinks properly.

For example, git installs two symlinks at /usr/bin/git-receive-pack and /usr/bin/git-upload-archive that point to /usr/bin/git. I'm not well versed in bash, but I think that $uwtwrapper_parent is incorrectly set to the symlink, rather than what the symlink points to. The script then tries to run /usr/bin/git-receive-pack.anondist-orig, rather than /usr/bin/git.anondist-orig. This causes the following error.

uwtwrapper uwt wrapper ERROR: /usr/bin/git-receive-pack.anondist-orig does not exist.

Details

Impact
Normal

Event Timeline

yzxd created this task.May 27 2018, 1:27 AM
Patrick triaged this task as Normal priority.May 27 2018, 7:08 AM
Patrick added a project: Whonix 15.
Patrick changed Impact from Needs Triage to Normal.
Patrick added a subscriber: HulaHoop.
yzxd added a comment.EditedMay 28 2018, 6:17 AM

I've created a pull request that fixes this issue here. It is a bit clunky since I'm not well-versed in bash, so any criticism is welcome.

Edit: This fixes the symlink part of the issue, but git appears to change behavior based on what symlink it was called by. I haven't a clue on how that would be fixed.

In T797#16103, @yzxd wrote:

I've created a pull request that fixes this issue here.

That looks really good!

Edit: This fixes the symlink part of the issue, but git appears to change behavior based on what symlink it was called by. I haven't a clue on how that would be fixed.

Dunno either how to fix. How does git figure out by which symlink it was called?

Does it help to add uwt wrappers for /usr/bin/git-receive-pack and /usr/bin/git-upload-archive? I guess either way we should add uwt wrappers for those?

yzxd added a comment.May 28 2018, 3:55 PM

How does git figure out by which symlink it was called?

I thought they were using some magic, but the program name is passed to it as the first argument and parsed here. So it takes git-receive-pack and makes it the same as git receive-pack.

After looking into it a bit further, there is definitely a way to fix it. You can emulate git-receive-pack by just calling exec -a git-receive-pack git without uwt. The -a argument passes its value as the first argument to the program.

Does it help to add uwt wrappers for /usr/bin/git-receive-pack and /usr/bin/git-upload-archive? I guess either way we should add uwt wrappers for those?

Adding wrappers for them does seem to fix the symbolic link issue without changing any of the code, but git still only gets /usr/bin/git.anondist-orig as its first argument. It might make sense to do so.

Sure. (Let's still fix the code to make it more resilient.)

yzxd added a comment.Jun 2 2018, 11:37 PM

I think I may have another solution that involves just adding the wrapper. If the wrappers were added for them and the symlink renamed to /usr/bin/git-receive-pack.anondist-orig, perhaps the symlink could be changed to point from /usr/bin/git to /usr/bin/git.anondist-orig. Would that still provide stream isolation?

As for fixing it in the code, I've done limited research so far. The exec "$uwtwrapper_parent.anondist-orig" "$@" cases at the end of the script could be fixed easily with the -a parameter. As for faketime, it appears that it does preserve the first argument (e.g., faketime 'yesterday' random-executable would pass it as random-executable, rather than faketime). I haven't tested time_privacy or torsocks yet.

In T797#16123, @yzxd wrote:

I think I may have another solution that involves just adding the wrapper. If the wrappers were added for them and the symlink renamed to /usr/bin/git-receive-pack.anondist-orig, perhaps the symlink could be changed to point from /usr/bin/git to /usr/bin/git.anondist-orig. Would that still provide stream isolation?

Not easy. Currently handled by config-package-dev (very reliable method). Better not mess with symlinks in other ways.

Patrick added a comment.EditedJun 5 2018, 5:27 PM
user@host:~$ ls -la /usr/bin/git-receive-pack 
lrwxrwxrwx 1 root root xxx 7 /usr/bin/git-receive-pack -> git

With your patch https://github.com/Whonix/uwt/pull/5 which is now merged....

export uwtwrapper_verbose=1
git-receive-pack clone https://github.com/Whonix/uwt.git

First execution of uwt.

exec git clone https://github.com/Whonix/uwt.git

Second execution of uwt.

exec torsocks /usr/bin/git.anondist-orig clone https://github.com/Whonix/uwt.git

Looks really good, right? Solved already?

/usr/bin/git-receive-pack symlinks to git.

/usr/bin/git symlinks to the bash based uwt wrapper git.anondist.

Interestingly during execution of /usr/bin/git, ${BASH_SOURCE[0]} will be set to /usr/bin/git-receive-pack.

This is what will happen during execution of /usr/bin/git.

export uwtwrapper_parent=/usr/bin/git-receive-pack
exec /usr/lib/uwtwrapper

What the user has run is git-receive-pack, which symlinked to git but what is actually running is /usr/lib/uwtwapper (while uwtwrapper_parent is being set to /usr/bin/git-receive-pack). So uwt falsely "thinks", that uwtwrapper_parent is /usr/bin/git-receive-pack, while actually git is the latest script that has executed /usr/lib/uwtwapper.


Related:

yzxd added a comment.EditedJun 6 2018, 11:08 PM

Looks really good, right? Solved already?

Yup, it's working great! I just tested git pushing to a server with uwt installed and the push went through successfully, so it appears git now gets the proper executable name (git-receive-pack). I think this should be safe to close now.

Edit: I didn't realize I had git-receive-pack symlinked to git.anondist-orig. The symlink issue is fixed, but it still only gets git as the first argument, rather than git-receive-pack. This causes git pushes to still fail, since git interprets git-receive-pack differently than just git. It should output something like You must specify a directory. with some other usage tips rather than the git help page.

Any exec -a command that would work?

If yes... We could uwtwrapper_parent into variable uwtwrapper_parent_previous and pass it to exec -a on nested execution of uwt (when uwtwrapper_counter is bigger than 1).

yzxd added a comment.Jun 15 2018, 4:19 AM

If yes... We could uwtwrapper_parent into variable uwtwrapper_parent_previous and pass it to exec -a on nested execution of uwt (when uwtwrapper_counter is bigger than 1).

For the simple exec "$uwtwrapper_parent.anondist-orig" "$@"s at the end of the script, I believe the -a parameter will work fine.

I tried testing exec -a git-receive-pack faketime "today" git as well as exec -a git-receive-pack torsocks git, but it doesn't appear that they pass the zeroth argument to the program and there's no similar -a parameter for them. The only solutions to these I can think of are another wrapper or filing a feature request with those projects.

The time_privacy script could probably be amended to allow a similar functionality to -a, since it's local to uwt (if it doesn't already, I haven't checked).

Btw don't mind faketime. I doubt anyone is using it. Might be because it
was never been documented.

So solution that only works with torsocks would be good enough and worth
merging.

yzxd added a comment.Jun 18 2018, 1:53 AM

I've created pull request #6 that fixes this issue and doesn't break any functionality. It adds a new wrapper (/usr/lib/uwtexec), which uses a new variable $uwtwrapper_zeroarg, $uwtwrapper_parent, and the original parameters ($@) to execute the program.

I haven't verified that torsocks still isolates the stream (I don't know enough to do so), but I believe it should still work normally.

Do we really need a new wrapper just for that? See T797#16131 how to do it without.

torsocks is configured to isolate per PID so it will probably still just work fine.

yzxd added a comment.Jun 18 2018, 8:46 PM

For exec calls without any wrappers (faketime or torsocks), the -a parameter will work fine.

For exec calls with wrappers, exec -a {zeroarg} torsocks program.anondist-orig will provide {zeroarg} as the zeroth argument to torsocks, but torsocks will not pass it onto program.anondist-orig. We could submit feature requests to the projects and ask for a parameter similar to exec's -a, but I'm not sure how long that would take for them.

Store it in a variable. Export. Read that variable and use it on nested
execution?

yzxd added a comment.Jun 20 2018, 3:57 AM

Do you mean something like exec {wrappers} exec -a $uwtwrapper_zeroarg $uwtwrapper_parent.anondist-orig $@? I can create a pull request for that but I'm not entirely sure if I'm understanding correctly.

See https://github.com/Whonix/uwt/pull/6/files#r196984725.

Do you think introducing a second wrapper cannot be avoided?

yzxd added a comment.EditedJun 22 2018, 3:12 AM

See https://github.com/Whonix/uwt/pull/6/files#r196984725.

That specifically won't work due to the wrappers not passing on the zeroth argument, but my above comment with the exec within an exec will work.

Do you think introducing a second wrapper cannot be avoided?

It can definitely be avoided, I just didn't realize it at the time. I'll close #6 and make another that doesn't require the additional wrapper.

I thought it could be avoided by using exec within an exec, but it turns out exec is a shell builtin and needs to be in a shell script. You can test this by running exec exec, which will return something like this: -bash: exec: exec: not found.

Patrick assigned this task to yzxd.Jun 22 2018, 6:05 AM

Merged. Added some commits on top. Uploaded to Whonix 14 testers repository. Please have a look and test.

https://github.com/Whonix/uwt/pull/6/files#r197324054

Did you test any application using bindp is still functional?

yzxd added a comment.Jun 23 2018, 6:12 PM

The two main issues of this issue, following symlinks and passing the zeroth argument properly, do work correctly now with the update in the testers repository.

torsocks stream isolation

I've tested that torsocks still isolates streams by changing its TorAddress in /etc/tor/torsocks.conf to 127.0.0.1, which didn't have a Tor daemon listening on it. For some strange reason, the change didn't apply immediately, but after a few minutes all binaries with wrappers failed to connect to the outside world.

bindp

On the first run, it failed instantly (for me), since I'm running Debian Stretch. The /sbin/ifconfig command no longer exists and the ip command is now recommended. This can be solved by installing the net-tools package, which provides /sbin/ifconfig.

On the second run with /sbin/ifconfig present, it fails with eth0: error fetching interface information: Device not found. This is due to Debian 9 using systemd 197+, which implements Predictable Network Interface Names. I'm not certain how we could fix the default, but I simply specified my interface's name by prefacing the command with bindp_interface=ens3.

On the third run, I got the error ERROR: ld.so: object '/usr/lib/libindp.so' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored., which means the bindp package was not installed.

On the fourth run with bindp installed, it succeeded without any error. I ran both bindp_dispatch=true BIND_ADDR="127.0.0.1" wget http://whonix.org and wget http://whonix.org. The first command failed (as it should, since it only allows local connections, see the second example on this) while the second command succeeded.

Could you try please any application depending on bindp is still functional? I guess onionshare would be the easiest.

https://www.whonix.org/wiki/Onionshare

Are you using uwt outside of Whonix? That's interesting! Didn't know that happens.

In Whonix we are disabling systemd predictable network interfaces.

I will fix the missing dependencies of uwt by adding bindp and net-tools to Depends:.

which didn't have a Tor daemon listening on it

btw that is related to https://www.whonix.org/wiki/Dev/anon-ws-disable-stacked-tor

yzxd added a comment.Jun 26 2018, 3:26 AM

Could you try please any application depending on bindp is still functional? I guess onionshare would be the easiest.

I've tried getting Onionshare v1.3.1 to work, but I'm stuck on step 7 on the wiki page you linked me. It mentions something about onion-grater, but that doesn't exist on my Gateway installation (13.0.0.1.4 for libvirt). I tried skipping the step, but it appears that it won't recognize the /var/run/tor/control and tries to fallback to Tor's control port at 127.0.0.1:9050.

I tried to circumvent this by just setting the control port to 10.152.152.10:9052 and the proxy to 10.152.152.10:9050, but it failed with the message Connected to 10.152.152.10:9052, but can't authenticate. Maybe this isn't a Tor controller?.

I then verified that the control port actually worked, by running telnet 10.152.152.10:9052 and got a 250 OK to the authenticate command.

I'm not really sure where to continue from here, I can't even get it to run on its own.

It needs to be developed and tested on Whonix 14.

yzxd added a comment.Jun 28 2018, 7:21 PM

It needs to be developed and tested on Whonix 14.

I must have missed the banner at the top of the page, whoops!

I just tested OnionShare on a fresh Whonix 14 installation using the latest uwt in the testing repository and it went a lot smoother than trying it with 13. After installing, I tried sharing a few files and it worked perfectly.

I also tested the version in the Debian testing repository and it seems they've updated it to version 1.3, but the current is 1.3.1.

Patrick closed this task as Resolved.Jun 29 2018, 5:54 AM

Awesome, thanks!

Thank you for your contribution, I would appreciate if keep contributing to Whonix!