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

fix: create windows npipe with the right security descriptor #4872

Closed

Conversation

profnandaa
Copy link
Collaborator

@profnandaa profnandaa commented Apr 24, 2024

There was already code that was creating the npipe with the right descriptors, as it has been for other like docker[1].

This fix uses the main.getLocalListener instead of the generic one from containerd/sys.

__
[1] https://github.com/moby/moby/blob/master/daemon/listeners/listeners_windows.go#L25

fixes #4864


Before and After (running from non-Admin terminal):

image

There was already code that was creating the npipe with the
right descriptors, as it has been for other like docker[1].

This fix uses the main.getLocalListener instead of the
generic one from `containerd/sys`.

fixes moby#4864

Signed-off-by: Anthony Nandaa <profnandaa@gmail.com>
@@ -639,6 +639,9 @@ func getListener(addr string, uid, gid int, tlsConfig *tls.Config) (net.Listener
if tlsConfig != nil {
bklog.L.Warnf("TLS is disabled for %s", addr)
}
if proto == "npipe" {
return getLocalListener(listenAddr)
}
return sys.GetLocalListener(listenAddr, uid, gid)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gabriel-samfira had also created getLocalListener for UNIX https://github.com/moby/buildkit/blob/master/cmd/buildkitd/main_unix.go#L51C1-L62 , which isn't being called...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly, the current getLocalListener() function is way to lax in terms of DACLs.

We need to parse the --group flag, resolve that to a SID, and use that SID to create a proper SDDL. We need to resolve the SID every time, because on Windows, the SID will always be different for each machine that was sysprepped. Also, if the machine is joined to an active directory, the group may be one belonging to AD, which will have a different SID compared to local groups. ie: you can have localhost\Docker and also mydomain\Docker.

The good news is that it should be easy to split the handling of the --group flag. If we omit it, we can default to none on Windows, and only allow the builtin Administrators group.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly, the current getLocalListener() function is way to lax in terms of DACLs.

Just double checking; that's the implementation in BuildKit only, correct? Because that one's missing this part of the code (to apply the group); https://github.com/moby/moby/blob/faf84d7f0a1f2e6badff6f720a3e1e559c356fff/daemon/listeners/listeners_windows.go#L29-L35

Or is the code in Moby also incorrect, by applying the fixed SID as starting point?;
https://github.com/moby/moby/blob/faf84d7f0a1f2e6badff6f720a3e1e559c356fff/daemon/listeners/listeners_windows.go#L26-L27

// allow Administrators and SYSTEM, plus whatever additional users or groups were specified
sddl := "D:P(A;;GA;;;BA)(A;;GA;;;SY)"

@profnandaa profnandaa marked this pull request as draft April 24, 2024 16:06
@colinhemmings
Copy link
Collaborator

@profnandaa I can test, but wait output do you get from running accesschk (Sysinternals Suite) against the buildkit pipe (\pipe\buildkit)?
Will this just open the pipe to anyone?

@tonistiigi tonistiigi marked this pull request as ready for review April 24, 2024 17:25
tonistiigi
tonistiigi previously approved these changes Apr 24, 2024
Copy link
Member

@tonistiigi tonistiigi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to check if this isn't relaxing security too much for default value and implement --group per #4864 (comment) , but I guess for testing experimental feature this is fine for now.

@profnandaa
Copy link
Collaborator Author

@profnandaa I can test, but wait output do you get from running accesschk (Sysinternals Suite) against the buildkit pipe (\pipe\buildkit)? Will this just open the pipe to anyone?

 accesschk.exe -d \\.\pipe\\buildkitd

Accesschk v6.15 - Reports effective permissions for securable objects
Copyright (C) 2006-2022 Mark Russinovich
Sysinternals - www.sysinternals.com

\\.\pipe\buildkitd
  RW NT AUTHORITY\Authenticated Users
  RW NT AUTHORITY\SYSTEM
  RW BUILTIN\Administrators

@profnandaa
Copy link
Collaborator Author

profnandaa commented Apr 24, 2024

We need to check if this isn't relaxing security too much for default value and implement --group per #4864 (comment) , but I guess for testing experimental feature this is fine for now.

@tonistiigi -- ok sure, created a tracking issue for that -- #4873 ; since Gabriel also had a TODO with the doubts.

@colinhemmings
Copy link
Collaborator

Yes, this now allows RW for any authenticated user, but it was previously allowing RO access for Everyone and ANONYMOUS LOGON.
I believe this will be sufficient for now, but before GA we will want to support the same approach to Moby, admin only, but allowing additional groups.

@gabriel-samfira
Copy link
Collaborator

We need to check if this isn't relaxing security too much for default value and implement --group per #4864 (comment) , but I guess for testing experimental feature this is fine for now.

@tonistiigi -- ok sure, created a tracking issue for that -- #4873 ; since Gabriel also had a TODO with the doubts.

I still have doubts about those permissions.

We should probably remove access for NT AUTHORITY\Authenticated Users, as this will allow any authenticated user to easily mount folders from the host system inside the container spawned by the buildkit executor. Buildkit runs as a privileged user by default (LocalSystem), as opposed to Linux which can run in unprivileged mode. It needs to in order to be able to use the local mounter functionality.

If we're in a rush now, allowing only Administrators and removing access for Authenticated users is desirable.

Long term, we should handle the --group option and use that. Most of that means creating Windows equivalent handling of the value passed into the --group option. That means looking up the group and resolving that to a SID. Then we can use that SID in an SDDL similar to the one in:

SecurityDescriptor: "D:P(A;;GRGW;;;AU)(A;;GRGW;;;SY)",

but with the resolved SID instead of AU (Authenticated Users),

I suggest we allow:

  • BUILTIN\Administrators
  • NT AUTHORITY\SYSTEM
  • The SID resolved from the --group flag

Copy link
Collaborator

@gabriel-samfira gabriel-samfira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For safety, we should either limit the named pipe to Administrators or properly handle the --group flag.

@profnandaa
Copy link
Collaborator Author

profnandaa commented Apr 24, 2024

@gabriel-samfira -- thanks for weighing in! Let me work on resolving the SID from the --group flag to close #4873 and #4864 altogether then. What's your take on what you'd started doing on the _unix.go side for getLocalListener()?

func getLocalListener(listenerPath string) (net.Listener, error) {
uid := os.Getuid()
l, err := sys.GetLocalListener(listenerPath, uid, uid)
if err != nil {
return nil, err
}
if err := os.Chmod(listenerPath, 0666); err != nil {
l.Close()
return nil, err
}
return l, nil
}

Do we fix that to get the --group flag too?

@tonistiigi -- I'll have to look at this (my) tomorrow, you may want to remove this from the v0.13.2 cherry-pick for now so that I don't hold that train back.

Thanks!

@tonistiigi
Copy link
Member

@profnandaa PR in #4875

@profnandaa
Copy link
Collaborator Author

closing in favor of #4875, thanks Tonis!

@profnandaa profnandaa closed this Apr 25, 2024
@profnandaa profnandaa deleted the fix-4864-npipe-sec-descriptor branch April 25, 2024 03:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Permissions issue when querying builder on Windows
5 participants