microsoft / vscode-remote-release

Visual Studio Code Remote Development: Open any folder in WSL, in a Docker container, or on a remote machine using SSH and take advantage of VS Code's full feature set.
https://aka.ms/vscode-remote
Other
3.67k stars 289 forks source link

sudo/root ports are not discovered #4654

Closed alexr00 closed 3 years ago

alexr00 commented 3 years ago

From @Chuxel:

There are three ports that are forwarded via forwardPorts in devcontainer.json. All three are valid and active.

Oddly two also do not say there are any running processes when in fact there is.

alexr00 commented 3 years ago

Based on the logs, VS Code's port discovery simply isn't finding these ports:

[2021-03-11 15:41:05.274] [exthost] [trace] ForwardedPorts: (ExtHostTunnelService) found candidate ports 5901, 5901

@Chuxel How are you starting the process that you expect to see on the other two ports? And, what do you expect the running process column to be (roughly)?

Chuxel commented 3 years ago

@alexr00 All three are started as a result of an ENTRYPOINT in the image. So they're effectively happening at OS start. This is essentially what gets invoked that triggers all three: /sbin/docker-init -- /usr/local/share/docker-init.sh /usr/local/share/ssh-init.sh /usr/local/share/desktop-init.sh sleep infinity

2222 is SSH, 5901 is VNC (which it is catching), and 6080 is a web server running the noVNC web client (which under the hood connects to 5901).

For 6080, I'd guess this would be:

python2 -m websockify --web /usr/local/novnc/noVNC-1.2.0/utils/../ 6080 localhost:5901

For 2222, I'd guess this would be:

/usr/bin/sshd

As I mentioned, 5901 is caught correctly as the following:

/usr/bin/Xtigervnc :1 -desktop codespaces_c5d1b0:1 (node) -auth /home/node/.Xauthority -geometry 1900x1200 -depth 24 -rfbwait 30000 -rfbauth /usr/local/etc/vscode-dev-containers/vnc-passwd -rfbport 5901 -pn -localhost -SecurityTypes VncAuth -screen :1 1440x768x16 -dpi 96 -desktop fluxbox
alexr00 commented 3 years ago

Thanks for all the details. I'm not familiar with how docker starts up containers, so these details made investigation much easier.

Findings for 6080: I found the process ID for the process running on 6080. In my case, it was 364. To associate the command line with the port number, we look at the proc filesystem, basically by doing:

ls -l /proc/364/fd

But for 364, I get a Permission denied. Running with sudo fixes that of course, but that's not an option from within VS Code.

I had some trouble finding the process for the other missing port, but I assume it's the same deal.

Looking at the ENTRYPOINT script (/usr/local/share/desktop-init.sh) I see this:

    keepRunningInBackground "noVNC" sudoIf "/usr/local/novnc/noVNC*/utils/launch.sh --listen ${NOVNC_PORT:-6080} --vnc localhost:${VNC_PORT:-5901}"

which looks to me as though the command that results in something listening on 6080 is running as sudo.

Since we can't read the command line from the proc filesystem from for commands run with sudo, this is by design. Is there any way the ENTRYPOINT scripts could be changed to not use sudo? Or is it required for those commands?

Chuxel commented 3 years ago

@alexr00 They are run as root rather than via sudo since this all happens before VS Code connects. This allows them to access system resources that a normal user can't. They're effectively daemons.

The sudoIf is there in the event that someone has set the default user to something other than root... which is not the case in this image.

Generally though this is a scenario we'll see. Doesn't a "permission denied" in this case confirm its presence? We could show it active even if we can't show the process that started it. The text could say "System process" or "Process running as root" in this case

alexr00 commented 3 years ago

I'll have to play around with how I can get the appropriate information. I say I got a "permission denied", but that was just from my testing. Getting all the ports doesn't result in "permission denied", but matching the port with a pid does.

In my testing, I skipped the step where the port is associated with a pid by doing some manual coming through processes and visual pattern matching. I might be able to come up with a heuristic (ex. run ps ax and look for the port number in the command lines), but I don't know how error prone that will be. I can try it and we'll see how it goes.

alexr00 commented 3 years ago

@Chuxel after doing some research, I found a way to get a bit better at finding the running process when the process is running as root. The heuristic is:

  1. Look a the command line (resulting from a ps exec) for all root processes for the port we know is being used, but whose process we can't find.
  2. If we find a process from step 1, find the "most child" process of that process since this is more likely to be correct then just finding the first process that has the missing port number in it's command line.

I think this will work most of the time, but I'm not a linux expert, so if someone knows of a reason this will be a problem I'm all ears.

There is one major drawback, and that's that the command line must include the port number for this to work at all. In your example with this repo it only works for port 6080, since that one is part of a command line. Port 2222 will not be caught by this.

I'm going to close this as the change improves things. If I find a better way, of course I will update. But I think this might be as good as its going to get.

Chuxel commented 3 years ago

Sounds good! Thanks for looking into it!