-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
x/sys/windows/svc : IsWindowsService doesn't work properly inside a windows container #56335
Comments
(CC @golang/windows) |
Thank you for creating this issue.
If you look at the code, you can see that Go code is copied from Microsoft .Net code: And that code still checks for sessionID of 0. Do you have any references that it is Thank you. Alex |
@alexbrainman Now I asked an official question to Microsoft. But their condition is probably just a safety guard to avoid a wrong interpretation if a process is spawned from a custom process named services.exe. |
@alexbrainman I have a very good news. The answer is already done. So x/sys should follow the same logic I think. |
(That was dotnet/runtime#52416.) |
@gillg sounds good to me. Do you want to send a CL? See https://go.dev/doc/contribute on how to contribute. Thank you. Alex |
@alexbrainman it's the weekend, so maybe I can succeed to follow the contribution guide 😆 I let you know if I don't have time or succeed to open a correct PR. By the way do you have an internal mechanic to observe changes to their runtime and see if changes in Golang are revelant ? |
Sounds good to me.
You need to run make.bash or make.bat (depending on the OS you are on) once do build Go. After that go command will automatically rebuild any changes you make in runtime package. But the fix for this issue will not require changing runtime package, but golang.org/x/sys/windows/svc package. Alex |
Sorry it was not clear, I was asking if the x/sys/windows Golang team was monitoring changes in the official Microsoft DotNet runtime. Just to be aware of this kind of things and report back potential security issues too. |
I don't monitor Microsoft DotNet runtime changes. I doubt anyone on Go Team monitors Microsoft DotNet runtime changes either. Alex |
Replied at https://go-review.googlesource.com/c/sys/+/446535 Alex |
FWIW, this seems like a pretty bad change. I don't mind following .NET, but doesn't this seem awfully brittle? You can just make your parent process named 'services.exe' and trick the test? Probably I should reverse engineer a bit and find something better. |
Definitely agree ! That's why I proposed to eventually use the session name as PR comment. |
The current IsWindowsService() function was inherited from the legacy .NET framework and not compatible inside windows containers. We need to update it so it works inside containers. References to: dotnet/runtime#52416 Fixes golang/go#56335
OpenSSL and httpd seems to be using |
Thanks @dims for your archeology ! |
+1 for this issue to be resolved, we are implementing native windows support for https://github.com/spiffe/spire using the svc lib, and we would appreciate the windows container compatibility for the IsWindowsService method. For now, we will be using a homemade version of this method with the same aforementioned dotnet/runtime fix. |
Hello @gillg You are not expected to do anything more. You did everything correctly at https://go-review.googlesource.com/c/sys/+/446535 . It is my turn to move this change forward. I did not comment here or on CL 446535 because I share Jason's concern (from #56335 (comment))
I was hopping Jason will make some suggestion on how to improve. But he did not comment more. Thanks to @dims for posting how other tools implement similar code at #56335 (comment) . But these approaches are very different from what current IsWindowsService does. How can we be sure that their code is better than what we already have? We don't want to break our existing users. How do we know their code actually works inside containers? Someone would have to try it before it can even be considered. I also had this idea. If we can find a way for a Windows process to determine if it is running inside of a container, then we can change IsWindowsService to run existing code if not inside of a container, and new .NET code if inside of a container. This will let our existing users run the same code as before, while container users will test new .NET code. Unfortunately I could not find a reliable way for a Windows process to determine if it is running in a container or not. I found many many ways to do it in Linux, like /proc/... or /.dockerenv files - https://www.thorsten-hans.com/check-if-application-is-running-in-docker-container . But none of them works in Windows according to https://www.thorsten-hans.com/check-if-application-is-running-in-docker-container/#what-about-windows-containers . The only thing we can try are described in https://stackoverflow.com/a/50748300/1390507 and https://stackoverflow.com/a/46810471/1390507 (I don't know how to implement second solution) I don't actually have Windows computer with containers. I cannot even try these things. So someone else needs to try these suggestions. I also opened to other ideas. Thank you. Alex |
Thanks @alexbrainman ! In my opinion working with the session name / windows station name is the more safe. Today windows only support docker and containerd is in a good position to be really supported soon. So regarding all that things, using the concept of session name seems really the best option and it seems not possible to spawn a process with this session name if you are not the "real" process services.exe. So for me the risk for existing users is probably null. |
I assume you are proposing not to go ahead with your https://go-review.googlesource.com/c/sys/+/446535 and instead rewrite IsWindowsService using either of those two approaches described at #56335 (comment) . If so, someone else would have to do it. And I suggest you also create a proposal about changing an implementation. Because I will not review the code unless others will agree with that change.
I am happy to accept whatever tricks we come up with, because IsWindowsService is broken on container now. So any improvement is good. What I don't want to happen is to break existing users. And using files under /proc seems safe enough in that regard. So if you can come up with a similar solution for Windows, I think that would be reasonable. Alex |
In fact I agree with you, just not on the form about trying to identify if we are inside a container or not. Merging the current PR seems pretty safe even if the solution from Microsoft is really discutable, and as you said, a next more open discussion to add the condition on the session name (or something better ?) could be a good option. |
I disagree. If you are talking about https://go-review.googlesource.com/c/sys/+/446535 , then I share Jason's opinion (from #56335 (comment)) that the CL makes it easy to trick IsWindowsService function. Alex |
This won't work by itself. In Windows Containers the only session is the "services" session. So apps running in containers that aren't Windows Services will get a false positive.
|
I hit this same issue and initially was thinking about asking for the fix proposed above. However, per recommendation of service API documentation programs should instead call It will be nice to add something like the above to the package documentation so others follow the pattern of checking the return of |
+1 to this. We use an MSI installer to create our windows service, and if it's the MSI installer that launched the service post-install, the session ID of services.exe is also != 0. So this is another instance apart from containers where the current implementation is not behaving accurately. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What did you do?
If I use IsWindowsService() inside a container servercore:ltsc2019 it always returns false, nevermind if I launch it as CLI or as service.
In windows containers world the service stack is native. It's not necessarly a "container pattern" but it's widely used for multiple reasons. So that method should work.
After some tests, the fail reason seems pretty simple.
On the host the "Session ID" of the process svchost.exe (for example) is 0, but inside the container, the "Session ID" of a process svchost.exe is 1.
The only process with a session ID 0 inside a container are :
But good news, the parent process is still "services.exe".
WmiApSrv is a random service (it's the native monitoring stack of windows)
I think, removing the condition
parentProcess.SessionID == 0
could be safe and fine... Any windows guru there ?In the meantime, the older deprecated funtion
IsAnInteractiveSession
is also buggy in a container, and never detects an interactive session even if you are in a CLI.The text was updated successfully, but these errors were encountered: