Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sudo and $HOME #29

Open
zertosh opened this issue Jan 10, 2020 · 19 comments
Open

sudo and $HOME #29

zertosh opened this issue Jan 10, 2020 · 19 comments

Comments

@zertosh
Copy link

zertosh commented Jan 10, 2020

When running with sudo, dirs-rs returns directories for the user calling sudo and not the user that's running under sudo.

On the surface this can seem like expected behavior but it becomes a real problem when a tool is run with sudo, uses dirs::cache_dir, and ends up creating that directory when it doesn't exist.

Unsetting $HOME before using dirs-rs causes dirs-sys-rs's home_dir to use getpwuid_r in the "fallback" logic. This ends up returning the home dir for the user running under sudo. But it's a really ugly workaround. Although sudo has an -H flag to replace $HOME, you don't tend to expect a tool to end up creating a ~/.cache owned by say root when you don't use -H.

I'm not sure if it's a good idea to never trust $HOME, but would it be possible to offer another set of methods that use the "real home dir"?

@soc
Copy link
Collaborator

soc commented Sep 12, 2021

A very good observation, thanks @zertosh! I'm trying to think of a solution that "just works" but haven't found anything yet ...

@ClementNerma
Copy link

There isn't an universal solution, but you can take a look at the SUDO_USER variable. It is defined by default when running sudo and contains the user that called sudo itself. AFAIK it is either defined with the correct user name, or not defined at all, it should never contain root unless the calling user was root itself.

@hulxv
Copy link

hulxv commented Jul 5, 2022

Hey, Was this issue solved or not yet?
I have the same problem, So, Is there any solution?

@Kyllingene
Copy link

I was looking at solving this, but the sudo manual describes SUDO_USER as "Set to the login name of the user who invoked sudo," although for me it remains unset. That seems like the bad behavior we're trying to avoid.

Would simply using the fallback function be an acceptable solution?

@mrjackwills
Copy link

I was looking at solving this, but the sudo manual describes SUDO_USER as "Set to the login name of the user who invoked sudo," although for me it remains unset. That seems like the bad behavior we're trying to avoid.

Would simply using the fallback function be an acceptable solution?

Can I ask which OS you were running with this behaviour?

I have just run into this sudo issue with an application I am working on, and on all the systems I've tested on (albeit on a couple of Ubuntu systems, and a couple or raspberry pi's running PiOs), the SUDO_USER is set, and could help solve this issue.

@Kyllingene
Copy link

Can I ask which OS you were running with this behaviour?

I was testing using Fish and Arch Linux. I can test again later using bash, perhaps?

@mrjackwills
Copy link

Ah ok, I'm only using bash.

Could a potential fix for this first check for SUDO_USER, and then fall back to USER? That's basically what I've implemented for my application, using the std::env::var("SUDO_USER") method, to return an Option<String>

@Kyllingene
Copy link

Kyllingene commented Jan 23, 2024

<currently on fish>
kyllingene@kyllingene ~> sudo echo $SUDO_USER

kyllingene@kyllingene ~> bash
[kyllingene@kyllingene ~]$ sudo echo $SUDO_USER

[kyllingene@kyllingene ~]$

I'm not getting SUDO_USER on either shell, odd.

Could a potential fix for this first check for SUDO_USER, and then fall back to USER?

Perhaps I'm misunderstanding, but I thought the goal was to make dirs::cache_dir et. al. return /root/* (or the equivalent) when running as root? Otherwise the behavior matches what we currently have, which leads to permissions issues.

@mrjackwills
Copy link

I have the same result with sudo echo $SUDO_USER, but try sudo printenv, that should - well it does for me - list a correct SUDO_USER

@Kyllingene
Copy link

Kyllingene commented Jan 26, 2024

You are correct. It's quite odd, because even using su gives me nothing:

[kyllingene@kyllingene ~]$ su
[kyllingene kyllingene]# echo $SUDO_USER

[kyllingene kyllingene]#

EDIT: A small test project using std::env::var also returns the proper value.

@soc
Copy link
Collaborator

soc commented Jan 26, 2024

So based on your observations y'all, is there any change that should be discussed?

@mrjackwills
Copy link

This issue I was having was that running an application via sudo would return the wrong home dir.

This program is called example

fn main() {
	let home = dirs::home_dir();
	println!("{home:?}")
}

Running ./example, this it prints Some("/home/jack"), but running sudo ./example it instead prints Some("/root").

I, although this may be a mistaken belief, think that both of these executions should return the same result, i.e. Some("/home/jack").

I haven't delved into the code properly, but my assumption was that the SUDO_USER env could help implement this.

@soc
Copy link
Collaborator

soc commented Jan 26, 2024

And now it seems that SUDO_USER is not set as expected?
Which, if we used SUDO_USER would lead to different results based on it being there, as far as I understand?

@mrjackwills
Copy link

I thought SUDO_USER was set as expected? It just only gets printed by printenv, rather than echo $SUDO_USER

But if not, maybe it could try to use SUDO_USER, and if this fails, fall back to the current implementation?

@soc
Copy link
Collaborator

soc commented Jan 26, 2024

I wonder where the different behavior comes from ...

@mrjackwills
Copy link

That I'm not sure, something about variable expansion happening before sudo is executed - which then doesn't inherit the expanded values?

@Kyllingene
Copy link

Kyllingene commented Jan 26, 2024

SUDO_USER is set properly when using std::env::var, which is all that really matters for this issue.

I'm thoroughly confused at this point. I tested with dirs{,_sys}::{home,cache}_dir, and I got /root and /root/.cache respectively (regardless of whether or not HOME was set). This differs from the behavior in the issue, and seems to me to be the expected behavior?

I, although this may be a mistaken belief, think that both of these executions should return the same result, i.e. Some("/home/jack").

This seems like something dirs-rs should support, but I disagree that it should be the default. If it were, it would lead to problems as described in the original issue (even if I can't reproduce them myself). However, something like user_home_dir could be useful, with documentation clarifying the difference. The trick would be making such a method cross-platform, to which I haven't given much thought yet.

@mrjackwills
Copy link

mrjackwills commented Jan 26, 2024

Yeah probably a good idea not to replace current behavior, and instead have a new function.

What cross platform issues do you envision? Running the aforementioned example application in Windows, as a normal user, and then as an elevated admin user, results in the same, correct, result each time Some("C:\\Users\\jack").

I don't currently have access to macOS, so sadly can't test on there

@Kyllingene
Copy link

That's true, Windows doesn't really have the same concepts so the two functions would essentially alias. I don't know what the behavior on Mac would be, perhaps someone here has one they could test on?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants