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

'Retry As Sudo' doesn't work to save a file #70403

Closed
lord-soth opened this issue Mar 13, 2019 · 45 comments
Closed

'Retry As Sudo' doesn't work to save a file #70403

lord-soth opened this issue Mar 13, 2019 · 45 comments
Assignees
Labels
info-needed Issue requires more information from poster upstream Issue identified as 'upstream' component related (exists outside of VS Code)

Comments

@lord-soth
Copy link

  • VSCode Version: 1.32.1
  • OS Version: Arch Linux 5.0.0-arch1-1-ARCH

Steps to Reproduce:

  1. Open and edit a file with root write permission
  2. Try to save it

When I try to edit and save a file with root permissions a prompt appears saying Failed to save httpd.conf. Insufficient permissions. Select Retry as Sudo to retry as superuser. When I click Retry as Sudo button same prompt reappears and file isn't saved. Prompt reappears every time I click the button.

I don't know if its relevant but I edited my sudoers file so sudo doesn't ask me for password:
alp ALL=(ALL) NOPASSWD: ALL

Does this issue occur when all extensions are disabled?: Yes

@vscodebot
Copy link

vscodebot bot commented Mar 13, 2019

(Experimental duplicate detection)
Thanks for submitting this issue. Please also check if it is already covered by an existing one, like:

@lord-soth
Copy link
Author

File is not read-only and is writeable by root so that issue is not relevant.

@bpasero
Copy link
Member

bpasero commented Mar 14, 2019

@lord-soth does it work if you do not do that?

I don't know if its relevant but I edited my sudoers file so sudo doesn't ask me for password:
alp ALL=(ALL) NOPASSWD: ALL

@bpasero bpasero added the info-needed Issue requires more information from poster label Mar 14, 2019
@lord-soth
Copy link
Author

lord-soth commented Mar 14, 2019

@bpasero It doesn't work also if I change it to:
alp ALL=(ALL) ALL

I can save if I start VSCode with superuser privilages but that is expected.

@bpasero
Copy link
Member

bpasero commented Mar 14, 2019

@lord-soth can you see if something is printed to the console when this happens? You can see output when you run with "code --verbose" and open the developer tools from the help menu

@jorangreef any hints what this could be? We are still using sudo-prompt module.

@lord-soth
Copy link
Author

@bpasero I think the relevant part is:

ERR doSave(4) - exit - resulted in a save error: Error: Permission denied writing to file (file:///etc/httpd/conf/httpd.conf) g {scheme: "file", authority: "", path: "/etc/httpd/conf/httpd.conf", query: "", fragment: "", …}authority: ""fragment: ""path: "/etc/httpd/conf/httpd.conf"query: ""scheme: "file"_formatted: "file:///etc/httpd/conf/httpd.conf"_fsPath: "/etc/httpd/conf/httpd.conf"fsPath: (...)proto: u

Failed to save 'httpd.conf': Insufficient permissions. Select 'Retry as Sudo' to retry as superuser.

onDidNotificationChange @ notificationsAlerts.ts:40
  _register.model.onDidNotificationChange.e @
  fire @
  notify @
  notify @
  onSaveError @
  onSaveError @
  i.force.dirty.inOrphanMode.i.reason.e.saveSequentializer.setPending.fileService.updateContent.then.e @
  Promise.then (async)  
  saveSequentializer.setPending.n.then.e @
  _tickCallback @
  Promise.then (async)  
  doSave @
  save @
  Promise.all.i.map.e @
  doSaveAllFiles @
  doSaveAll @
  saveAll @
  save @
  P @
  handler @
  invokeFunction @
  _tryExecuteCommand @
  r.then.i @
  Promise.then (async)  
  executeCommand @
  y.ipcRenderer.on @
  emit

@bpasero
Copy link
Member

bpasero commented Mar 14, 2019

@lord-soth yeah that is the first part of the error which is to be expected because this triggers the prompt to save as admin.

I you are up to it, can you try to reproduce just using the https://github.com/jorangreef/sudo-prompt module? This is what VSCode is using after all.

@lord-soth
Copy link
Author

lord-soth commented Mar 14, 2019

@bpasero I checked that the sudo-prompt node package is not installed so I installed it.

code $ sudo npm install -g sudo-prompt
+ sudo-prompt@8.2.5
added 1 package from 1 contributor in 0.648s

I executed test.js provided by sudo-prompt package to make sure sudo-prompt works correctly. Password prompt appeared and I entered my password. It seems to work.

sudo-prompt $ node test.js
sudo.exec("echo hello", {"name":"Electron"})
error: null
stdout: "hello\n"
stderr: ""
OK

I executed npm install in VSCode directory to make sure dependencies are installed.

code $ ls
code.js     LICENSE.txt        node_modules.asar.unpacked  package.json       product.json  ThirdPartyNotices.txt
extensions  node_modules.asar  out                         package-lock.json  resources
code $ npm install
npm WARN Invalid name: "Code - OSS"
npm WARN code No description
npm WARN code No repository field.
npm WARN code No README data
npm WARN code No license field.

up to date in 1.031s
found 0 vulnerabilities

However there is no change in VSCode. I don't know how VSCode uses sudo-prompt so I can't investigate the issue. Also I have no experience with NodeJs or Electron so I don't think I can debug by myself.

@bpasero
Copy link
Member

bpasero commented Mar 14, 2019

@lord-soth ok, there is more things we can try. If you tell VSCode to save as sudo, the following will happen:

  • we write the desired contents into a temp file (here)
  • we import sudo-prompt (here)
  • we ask it to run "code --file-write tmpfile target"

It is possible that this fails, maybe you could change your script to exercise the same things?

@lord-soth
Copy link
Author

@bpasero I don't have the time and don't have the java/js experience(I am a c++ dev) to debug this but if you give me a script/executable to run I can try. Maybe in the near future I can try to debug.

@jorangreef
Copy link

Thanks @lord-soth for running the sudo-prompt test.

If that passes, then I don't think it's anything specific to your Arch Linux system or your sudoers file.

@bpasero , thanks for the heads up. I will keep tabs on this and will still look into the fileService.ts references you posted to see if I can find anything.

@bpasero
Copy link
Member

bpasero commented Mar 14, 2019

@lord-soth in your script, just try this:

sudo.exec("code --file-write <some existing file> <some new file>", {"name":"Code"})

And see if that works or throws an error.

@jorangreef thanks, I would assume this is probably specific to @lord-soth configuration as I have not heard any issues from any other users so far.

@lord-soth
Copy link
Author

@bpasero

scripts $ node test.js
/home/alp/scripts/test.js:1
sudo.exec("code --file-write /etc/httpd/conf/httpd.conf /home/alp/scripts/test", {"name":"Code"});
^

ReferenceError: sudo is not defined
    at Object.<anonymous> (/home/alp/scripts/test.js:1:1)
    at Module._compile (internal/modules/cjs/loader.js:799:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:810:10)
    at Module.load (internal/modules/cjs/loader.js:666:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:606:12)
    at Function.Module._load (internal/modules/cjs/loader.js:598:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:862:12)
    at internal/main/run_main_module.js:21:11

@bpasero
Copy link
Member

bpasero commented Mar 14, 2019

@lord-soth sorry, you need to require the module too: require("sudo-prompt").exec("code --file-write <some existing file> <some new file>", {"name":"Code"})

@lord-soth
Copy link
Author

@bpasero

scripts $ cat test.js
require("sudo-prompt").exec("code --file-write /etc/httpd/conf/httpd.conf /home/alp/scripts/test", {"name":"Code"})
scripts $ node test.js
internal/modules/cjs/loader.js:651
    throw err;
    ^

Error: Cannot find module 'sudo-prompt'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:649:15)
    at Function.Module._load (internal/modules/cjs/loader.js:575:25)
    at Module.require (internal/modules/cjs/loader.js:705:19)
    at require (internal/modules/cjs/helpers.js:14:16)
    at Object.<anonymous> (/home/alp/scripts/test.js:1:1)
    at Module._compile (internal/modules/cjs/loader.js:799:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:810:10)
    at Module.load (internal/modules/cjs/loader.js:666:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:606:12)
    at Function.Module._load (internal/modules/cjs/loader.js:598:3)

@bpasero
Copy link
Member

bpasero commented Mar 14, 2019

@lord-soth we are getting there :).

Can you:

  • create a new folder
  • create a package.json with the content below
  • run "npm install"
  • create a index.js file with the content I mentioned above
  • run node index.js from the command line

package.json:

{
    "name": "name",
    "description": "description",
    "authors": "author",
    "version": "1.0.0",
    "main": "pathToMain",
    "dependencies": {
        "sudo-prompt": "8.2.5"
    }
}

@lord-soth
Copy link
Author

@bpasero
Authentication prompt appears saying "Authentication is needed to run 'usr/bin/code' as the super user". This is the same prompt I get when I run the sudo-prompt's test.js. I enter the password and click authenticate. Prompt closes without any output at terminal.

@bpasero
Copy link
Member

bpasero commented Mar 14, 2019

@lord-soth ok and does it actually write the file properly? can you check?

@lord-soth
Copy link
Author

@bpasero
No it doesn't create the new file. It should create /home/alp/scripts/test file but it doesn't exist.

@bpasero
Copy link
Member

bpasero commented Mar 14, 2019

@lord-soth sorry, this will actually only work if the file exists, I just realize. So please try again with a target file that exists too.

@lord-soth
Copy link
Author

@bpasero I created the file. It doesn't write, size is 0.

@bpasero
Copy link
Member

bpasero commented Mar 14, 2019

@lord-soth does it print anyoutput when you use "code --verbose" instead of just "code" in your script.

@lord-soth
Copy link
Author

@bpasero No, adding --verbose doesn't print any output.

@bpasero
Copy link
Member

bpasero commented Mar 14, 2019

@lord-soth is something printed if you just literally run code --verbose --file-write <some existing file> <some other existing file> from the console?

@lord-soth
Copy link
Author

@bpasero

scripts $ code --verbose --file-write /etc/httpd/conf/httpd.conf /home/alp/scripts/test
Error using --file-write: EACCES: permission denied, open '/etc/httpd/conf/httpd.conf'

@lord-soth
Copy link
Author

If code --verbose --file-write <some existing file> <some other existing file> is opening existing file to copy then there shouldn't be permission denied errors. Because I can copy it with cp command:
test-dir $ cp /etc/httpd/conf/httpd.conf ./http-copy
And it successfully copies the content to new file.

@bpasero
Copy link
Member

bpasero commented Mar 14, 2019

@lord-soth just to double check: there are a few assumptions in VSCode to make the file-write argument work. The 2 files have to exist and the paths you provide have to be absolute and cannot be the same. You did that right when you tested with the sudo-prompt script? Two different paths that exist as absolute paths?

I wonder if sudo-prompt might end up running Code with a different user compared to what your sudo command would do....

@bpasero bpasero added the upstream Issue identified as 'upstream' component related (exists outside of VS Code) label Mar 14, 2019
@lord-soth
Copy link
Author

@bpasero Below you can see that I am doing what you want me to do. I copied it from the terminal without modifying the order:

vscode-test $ ls
index.js  package.json  test
vscode-test $ cat package.json
{
    "name": "name",
    "description": "description",
    "authors": "author",
    "version": "1.0.0",
    "main": "pathToMain",
    "dependencies": {
        "sudo-prompt": "8.2.5"
    }
}
vscode-test $ npm install
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN name@1.0.0 No repository field.
npm WARN name@1.0.0 No license field.

added 1 package from 1 contributor and audited 1 package in 1.699s
found 0 vulnerabilities

vscode-test $ cat index.js
require("sudo-prompt").exec("code --file-write --verbose /etc/httpd/conf/httpd.conf /home/alp/scripts/vscode-test/test", {"name":"Code"});
vscode-test $ ls -l /etc/httpd/conf/httpd.conf
-rw-r--r-- 1 root root 20377 Mar 14 11:05 /etc/httpd/conf/httpd.conf
vscode-test $ ls -l /home/alp/scripts/vscode-test/test
-rw-r--r-- 1 alp alp 0 Mar 15 10:27 /home/alp/scripts/vscode-test/test
vscode-test $ node index.js
vscode-test $ ls -l /home/alp/scripts/vscode-test/test
-rw-r--r-- 1 alp alp 0 Mar 15 10:27 /home/alp/scripts/vscode-test/test

You can see that httpd.conf file size is 20377 but size of test file remains 0.

@jorangreef
Copy link

@lord-soth, just a nit:

The binary path passed to sudo-prompt must be absolute not relative.

i.e. You should provide the full path to the code binary.

I am not sure if that's the cause of this, but that will help you avoid shadowing issues.

@lord-soth
Copy link
Author

@jorangreef Changed code to /usr/bin/code in the script but made no difference.

@jorangreef
Copy link

Thanks @lord-soth

Can you try another version of your index.js where you substitute the code command for something like cp or whatever will have the same effect?

@lord-soth
Copy link
Author

@jorangreef No problem. I created a new script:

vscode-test $ cat index_cp.js
require("sudo-prompt").exec("/usr/bin/cp /etc/httpd/conf/httpd.conf /home/alp/scripts/vscode-test/test");

It correctly copies httpd.conf to test without any output at terminal.

@rocka
Copy link

rocka commented Mar 27, 2019

It seems that code --file-write does not work regardless what arguments it was given:

$ stat /tmp/sudotest/index.js
  File: /tmp/sudotest/index.js
  Size: 281             Blocks: 8          IO Block: 4096   regular file
Device: 2dh/45d Inode: 191907      Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/   rocka)   Gid: ( 1000/   rocka)
Access: 2019-03-27 13:48:06.713222257 +0800
Modify: 2019-03-27 13:48:37.976633050 +0800
Change: 2019-03-27 13:48:37.976633050 +0800
 Birth: -
$ stat /tmp/a.js
stat: cannot stat '/tmp/a.js': No such file or directory
$ ./code --file-write /tmp/sudotest/index.js /tmp/a.js
Using --file-write with invalid arguments.
$ ./code --file-write /tmp/a.js /tmp/sudotest/index.js
Using --file-write with invalid arguments.
$ ./code --file-write
Using --file-write with invalid arguments.

Maybe it has something to do with argv parsing issues?

OS and VSCode versions:

$ uname -sr
Linux 5.0.4-arch1-1-ARCH
$ ./code --version
1.32.3
a3db5be9b5c6ba46bb7555ec5d60178ecc2eaae4
x64

VSCode was downloaded from https://code.visualstudio.com/#alt-downloads Linux .tar.gz 64 bit version.

That ./code exectuable was VSCode-linux-x64/bin/code

@bpasero
Copy link
Member

bpasero commented Mar 27, 2019

@rocka both source and target have to exist and have to be absolute file paths

@rocka
Copy link

rocka commented Mar 27, 2019

@bpasero Sorry for that mistake ... then I got some test again:

$ sudo ./code --verbose --file-write /tmp/sudotest/index.js /tmp/a.js
Error using --file-write: EACCES: permission denied, open '/tmp/a.js'

$ pkexec $PWD/code --verbose --file-write /tmp/sudotest/index.js /tmp/a.js
Error using --file-write: EACCES: permission denied, open '/tmp/a.js'

$ ./code --verbose --file-write /tmp/sudotest/index.js /tmp/a.js
(works as expected)

$ su root
Password:
# ./code --verbose --file-write /tmp/sudotest/index.js /tmp/a.js
Error using --file-write: EACCES: permission denied, open '/tmp/a.js'

According to sudo-prompt's source code, pkexec should be used under this circumstance. But running code with sudo or pkexec cannot write file correctlly, switch to root user performs the same.

@bpasero
Copy link
Member

bpasero commented Mar 27, 2019

@rocka if using sudo still results in a permission denied error than this hardly sounds like an issue with VSCode but rather the configuration of the OS and file system, no? Does it work if you use vi or any other editor with sudo?

@rocka
Copy link

rocka commented Mar 27, 2019

@bpasero Oh yes... Only file in /tmp cannot be written, if place the file under somewhere else, everything works fine.

I'm sorry for such a mistake ...

I think this should be a problem with package code in repo community of Arch Linux.

@bpasero
Copy link
Member

bpasero commented Mar 27, 2019

Oh wow this is Arch Linux, yeah likely.

@bpasero bpasero closed this as completed Mar 27, 2019
@lord-soth
Copy link
Author

@bpasero So what is the solution

@rocka
Copy link

rocka commented Mar 27, 2019

@lord-soth
Copy link
Author

lord-soth commented Mar 27, 2019

@rocka Installing the aur package solved the issue. Thank you.

@h1nk
Copy link

h1nk commented Apr 4, 2019

Why is it that the 'Retry As Sudo' functionality works fine for the binary package but fails when VSCode is installed with a normal package manager like pacman or apt/dpkg --install? This doesn't really seem solved to me as having to use the binary installation isn't preferable.

@rocka
Copy link

rocka commented Apr 5, 2019

@h1nk The feature works fine if you install vscode via Microsoft official repo mentioned in #2973 (comment)

As for Arch Linux's pacman repo, it's a packaging issue: https://bugs.archlinux.org/task/61516

@h1nk
Copy link

h1nk commented Apr 6, 2019

@rocka I've installed code via the official Microsoft apt repository per the instructions from that link and I'm still experiencing the same issue mentioned in this thread. This issue seems to apply not just to Arch's package distribution but the apt package from Microsoft as well.

@rocka
Copy link

rocka commented Apr 7, 2019

@h1nk If so I think you should open a new issue, it works fine on my machine ...

@vscodebot vscodebot bot locked and limited conversation to collaborators May 11, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
info-needed Issue requires more information from poster upstream Issue identified as 'upstream' component related (exists outside of VS Code)
Projects
None yet
Development

No branches or pull requests

5 participants