-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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
linux: Fix saving file with root ownership #22045
linux: Fix saving file with root ownership #22045
Conversation
@mikayla-maki moved it to a separate optional script, as you asked. Also added docs for it in |
@0xtimsb thanks for making that change That said, I think my suggestion has terrible UX… could we do something like detect if the user has Polkit installed, and then prompt them if they want to install our policy, and only then escalate the script’s permissions to su so we can do the installation? |
script/install.sh
Outdated
echo "Zed needs sudo access to improve root file editing experience." | ||
printf "Configure polkit? [Y/n] " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could potentially be more beginner-friendly if worded as something like "Configure polkit to allow Zed to request elevated permissions when editing system files?"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, not super accurate (since it’d still work even after saying no), but let’s just write it this way for simplicity's sake.
crates/fs/src/fs.rs
Outdated
let mut cmd = Command::new(pkexec_path); | ||
cmd.arg("--disable-internal-agent"); | ||
|
||
let script_path = PathBuf::from("/usr/libexec/zed/elevate.sh"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also not going to work on NixOS. Would be nice to have a way to specify this as a command line flag or env variable while building so we don't have to resort to patching the code in the NixOS package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’ve added the env variable which can be used in Nix installation. But, I'm not picking that in this PR as I'm not familiar with Nix yet. It should still work on NixOS as long as pkexec is in the PATH without custom message. I will create another PR after setting up NixOS VM and testing there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! In nixpkgs we wrap the executable in a shell script to add node.js into its PATH already so adding pkexec in that mix is trivial. Similarly setting the environment variable for the elevate script to point to /nix/store/<hash>
is easily doable now. Updating the nix files in this repo can indeed be done separately (especially since this is not a change that breaks something that was working before).
@0xtimsb thanks for this! We should not add this functionality to the install.sh script. It should not prompt (so that it can be run in people's setup scripts without needing arguments to skip prompts) and it should not write outside of your home directory or ask for root (so that anyone can install Zed on any machine). If we need polkit support for this feature, we should defer installing it to later as we do with the Is there a way of building this feature that does not require configuration changes on the machine? It sounds like we could get the same behavior as VSCode without it. If so that seems like the better trade-off (and if we call the script something like |
@ConradIrwin thanks for the suggestions! I've removed the policy and custom script, so there are no changes to the installation process now. I went with a similar approach to VSCode, creating a temporary script during runtime instead of setting up a script during the Zed installation. It’s much simpler now - just the script name shows up in prompt instead of a bunch of arguments, so it’s clearer. This should also work on NixOS. |
Beyond the blocking IO, this implementation looks great! |
e6a8cb4
to
ff8b062
Compare
This PR implementation looks good, and no longer changes our install script at all, so I'm going to merge it. |
Just got the notification that this PR existed otherwise I would have been here sooner. The polkit file isn't in the changes anymore, is that intentional? I looked back at the history for it, and the following:
Should be
Yeah this is completely insecure. This opens up the attack vector that the script can be modified by another process between it being written and it being executed allowing that process to execute arbitrary code as root with the user being none the wiser. The initial design of having a separate script that was installed by the install script was the correct one as, assuming Zed is installed to a system location that the user executing Zed does not have direct write access to, it completely mitigates that vector of attack. Instead of using a script you could use a dedicated binary (faster, some systems have profile scripts that may introduce noticeable delay while a binary will be more consistent) or have a separate "command" that zed understands so it can pkexec itself. You should also hash the file contents and pass that hash to the helper script/binary so that it can verify that the temporary file hasn't been modified by another process. |
If you use the official installer script this won't be the case. |
Isn't risk is more if script is pre-defined at some location (usually in .local dir)? This is also how VSCode currently does it, here. |
I don't believe that that is true. I instrumented process execution on my machine (using execsnoop from bcc) and see the following process started by vscode:
Crucially we see that vscode is executing itself with the Though vscode doesn't implement it this could be further improved by checksumming the temporary file and passing that checksum to the "root" process, not sure why they're not doing that. Additionally there's a bit of logic to prevent vscode from being ran as root unless that flag is passed here, which is probably a good idea to implement as well if similar does not already exist. |
Alright it's been two weeks since I reported this security issue and I don't see any follow-up PRs addressing the insecure behavior. If my understanding of the release schedule is correct this is going to go out to users next week correct? I suppose I'll have to file a CVE if that happens, I don't see that Zed currently has a CPE, I suppose the correct one to create would be CC @ConradIrwin |
Hi, @ReillyBrogan I have few questions regarding this, I would like if we can figure out some actionables to follow up security issues you mentioned. FYI, I'm not associated with Zed, just an external contributor.
I don’t understand how this differs from the current implementation. I see, instead of a script containing the file content, we have a script that points to the file path. But both approaches are similar in terms of temporary script creation, execution, and deletion. So, doesn’t VS Code’s script also have the same mentioned vulnerability when it comes to modifying the script?
We are not replacing the target file, only modifying its content, so the existing permissions will remain unchanged. The ownership may change to root, but since the file is already owned by root, this should not be an issue? |
@ReillyBrogan Sorry for the slow reply here. To summarize the problem:
Do I understand the threat model correctly? It seems like we can simplify the implementation to avoid the issue by doing:
and passing input on STDIN. This avoids the need for an extra shell-script, and avoids the ability for the rogue entity to edit the copy of the file on disk. Does that fix the problem for you? I'm not sure it's a huge issue (an actor with the ability to edit your files can achieve more reliable success by changing your shell configuration to make |
@0xtimsb I noticed when working on #22843 that while saving seems to work fine, we never get a notification that the file has changed on disk, and so Zed continues to think the file is unsaved/has a conflict. Did you also experience that in the first implementation, or is there something different about our setups? |
Oh wait, I misunderstood your question. I tried this (#22843), and something similar to what you're experiencing happened to me while working on it. I don't quite remember how I fixed it. I'm debugging. The current latest preview works on my machine. |
This reverts commit f64bfe8.
This reverts commit f64bfe8.
Closes #13585
Currently, saving files with
root
ownership orroot
as the group throws aPermission denied (os error 13). Please try again.
error. This PR fixes the issue on Linux by prompting the user for a password and saving the file with elevated privileges.It uses
pkexec
(Polkit), which is by default available on GNOME, KDE, and most Linux systems. I haven't implemented this for macOS as I don't have a device to test it on.This implementation is similar to how Vscode handles it. Except, they don't show custom message.
Working:
When file saving fails due to a
PermissionDenied
error, we create a temporary file in the same directory as the target file and writes the data to this temporary file. After, the contents of this file are copied to the original file using thetee
command instead ofcp
ormv
. This ensures that the ownership and permissions of the original file are preserved. This command is executed usingpkexec
which will prompt user for their password.Custom Message:
The message displayed to the user in the prompt is automatically retrieved from the
org.zed.app.policy
file, which is located at/usr/share/polkit-1/actions/
. This file should be installed during the setup process. While the policy file is optional, omitting it will cause the user to see the underlying command being executed rather than a user-friendly message. Currently, VSCode does not display the user-friendly message.The policy file must specify a unique binary, ensuring that only that binary can use the policy file. It cannot be as generic as a
/bin/bash
, as any software using bash to prompt will end up showing Zed’s custom message. To address this, we will create a custom bash script, as simple as the following, placed in/usr/bin/zed/elevate.sh
. The script should have root ownership and should not reside in the home directory, since the policy file cannot resolve$HOME
.IMPORTANT NOTE
Since copying the policy file and our script requires sudo privileges, the installation script will now prompt for the password at very end. Only on Linux, if
pexec
is installed.Screenshots:
KDE with policy file:
Gnome with policy file:
Gnome without policy file:
VSCode:
User declines the permission request:
Release Notes: