-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Add a new RPC ConnectWithCreds
to allow gofer to connect to a unix domain socket with application's credentials
#11291
Add a new RPC ConnectWithCreds
to allow gofer to connect to a unix domain socket with application's credentials
#11291
Conversation
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
I will prepare some sample code to reproduce this issue. Databricks should already have the CLA with Google. I will ask our PoC to include me in the group of contributors. |
Is the server using I understand that your situation is different, but could you use the same logic in your case? To cc @avagin about implications of running the gofer with euid= |
Thanks for the fast reply! Yes the server uses We cannot use file permission because, there is only one unix domain socket file on the host, which the server listens to. This unix domain socket file is mapped to every sandbox' filesystem, i.e. every sandbox should have the capability to talk to the server over this unix domain socket. The server utilizes the |
Would this problem be solved by running sandboxes in |
Yeah we considered this. However this comes with the cost of much weakened security guarantees, for example the sandbox's isolated network stack cannot be used. Directfs can also not be used. I think in general the sandbox's host-filesystem-access shouldn't be performed with a root entity. This is already a security concern. What do you think? |
The gofer is running in a pivot_root(2) which only has the container filesystem (the rootfs + any bind mounts) mounted in it. But yes it can create the gvisor/runsc/fsgofer/lisafs.go Lines 617 to 620 in bd0cbf8
So the gofer runs as root and changes UID/GID for created files based on the application thread's UID/GID. I think running as root is also needed for the special capabilities that the gofer needs to run with: Lines 47 to 62 in bd0cbf8
I think we can make an exception for Lines 1296 to 1306 in bd0cbf8
|
@ayushr2 Thank you so much for your detailed reply!
However the bind mounts represent files on host filesystem. The sandbox's file access to bind mounts is performed with root privilege due to gofer. Would this already be a security concern?
The application usually runs as non-root. How is it possible/ What are the cases for a non-root to change its euid at runtime (besides the corner case of changing to its ruid or saved uid)?
I have two concerns here:
|
Also a follow-up question:
Then what happens with the Also aren't linux capabilities designed to grant non-root processes the fine-grained root-like privileged actions? I think just because we grant gofer these capabilities, gofer can run without root Lines 47 to 62 in bd0cbf8
I also verified that the |
Note that the sentry does all necessary filesystem permission checks and only makes authenticated RPCs to the gofer, after which the gofer takes actions as root to fulfill the filesystem request. The attacker needs to compromise the sentry to bypass sentry checks and make arbitrary RPCs to the gofer. Even if that does happen, then our second layer of defense here is the gofer. It limits the attacker to just the filesystem that has been exposed to the container via bind mounts and prevents the attacker from accessing the host filesystem. That being said, if we can actually run the gofer in non-root user, it would be nice.
I believe it is possible that the user can call
setuid/setgid only changes the users/groups for the current system thread. So we need to use |
Please squash all your commits into 1, because all commits from this branch will be applied directly to master if we were to merge this. |
Thanks for reminding this! I will keep the commit history as-is for the moment, and when we are ready to merge, I squash all the commits and do a force-push. |
ConnectWithCreds
to allow gofer to connect to a unix domain socket with application's credentials
@ayushr2 could you approve of the github workflows to see how tests are going? Thank you so much! |
@ayushr2 Happy new year and thank you so much for the guidance along the way. I did a final check and made sure the unit tests and integration tests passed. The fix is needed by us urgently. I really appreciate it if we could make the fix included in next week's release. Could you let me know what else is left for the merge (besides squashing the commits)? |
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.
Just nits, mostly LGTM
Its probably time to squash all commits BTW. |
c97215d
to
bb00c42
Compare
…main socket with application's credentials
bb00c42
to
c4f686f
Compare
Thanks. The commits were squashed. |
Just did another final check. The PR can be merged from our side. Thank you so much! |
@ayushr2 shall we create a copybara PR for this one? Will we able to include it in this week's release? Thanks! |
Its undergoing internal review and needs approval from someone other than me since I approved it here. I don't think we will be able to make it into this week's release. |
I see. Thanks for informing me! |
…domain socket with application's credentials Dear gvisor developers, Thank you very much for maintaining / developing gvisor! ## Motivation We had a use case (which I believe is a wide use case) that the sandboxes send requests over a unix domain socket on host, which is mapped to the container's file system and listened to by a server on the local host. The sandboxed application is started with a prescribed uid. To authenticate the request, the server verifies the request's uid. However, as the gofer process (which usually runs as root) executes [connect(unix_domain_socket) call](https://github.com/google/gvisor/blob/bd0cbf807169db29837d238209c02c816f3c8dbf/runsc/fsgofer/lisafs.go#L819) on behalf of the sandbox, the server always sees a uid 0. Hence the server cannot authenticate the UDS requests coming from the sandbox. ## Proposal I propose to Add a new RPC `ConnectWithCreds` to allow gofer to connect to a unix domain socket with application's credentials. On that gofer server thread, the euid/egid are temporarily changed to application's uid/gid and restored after the `connect(2)` call. ## Questions What do you think of this change? Is there any security/ functionality concern? Thank you so much for your feedback! FUTURE_COPYBARA_INTEGRATE_REVIEW=#11291 from xianzhe-databricks:fix-uds-auth c4f686f PiperOrigin-RevId: 712489714
…domain socket with application's credentials Dear gvisor developers, Thank you very much for maintaining / developing gvisor! ## Motivation We had a use case (which I believe is a wide use case) that the sandboxes send requests over a unix domain socket on host, which is mapped to the container's file system and listened to by a server on the local host. The sandboxed application is started with a prescribed uid. To authenticate the request, the server verifies the request's uid. However, as the gofer process (which usually runs as root) executes [connect(unix_domain_socket) call](https://github.com/google/gvisor/blob/bd0cbf807169db29837d238209c02c816f3c8dbf/runsc/fsgofer/lisafs.go#L819) on behalf of the sandbox, the server always sees a uid 0. Hence the server cannot authenticate the UDS requests coming from the sandbox. ## Proposal I propose to Add a new RPC `ConnectWithCreds` to allow gofer to connect to a unix domain socket with application's credentials. On that gofer server thread, the euid/egid are temporarily changed to application's uid/gid and restored after the `connect(2)` call. ## Questions What do you think of this change? Is there any security/ functionality concern? Thank you so much for your feedback! FUTURE_COPYBARA_INTEGRATE_REVIEW=#11291 from xianzhe-databricks:fix-uds-auth c4f686f PiperOrigin-RevId: 712489714
…domain socket with application's credentials Dear gvisor developers, Thank you very much for maintaining / developing gvisor! ## Motivation We had a use case (which I believe is a wide use case) that the sandboxes send requests over a unix domain socket on host, which is mapped to the container's file system and listened to by a server on the local host. The sandboxed application is started with a prescribed uid. To authenticate the request, the server verifies the request's uid. However, as the gofer process (which usually runs as root) executes [connect(unix_domain_socket) call](https://github.com/google/gvisor/blob/bd0cbf807169db29837d238209c02c816f3c8dbf/runsc/fsgofer/lisafs.go#L819) on behalf of the sandbox, the server always sees a uid 0. Hence the server cannot authenticate the UDS requests coming from the sandbox. ## Proposal I propose to Add a new RPC `ConnectWithCreds` to allow gofer to connect to a unix domain socket with application's credentials. On that gofer server thread, the euid/egid are temporarily changed to application's uid/gid and restored after the `connect(2)` call. ## Questions What do you think of this change? Is there any security/ functionality concern? Thank you so much for your feedback! FUTURE_COPYBARA_INTEGRATE_REVIEW=#11291 from xianzhe-databricks:fix-uds-auth c4f686f PiperOrigin-RevId: 712489714
Dear gvisor developers,
Thank you very much for maintaining / developing gvisor!
Motivation
We had a use case (which I believe is a wide use case) that the sandboxes send requests over a unix domain socket on host, which is mapped to the container's file system and listened to by a server on the local host.
The sandboxed application is started with a prescribed uid. To authenticate the request, the server verifies the request's uid.
However, as the gofer process (which usually runs as root) executes connect(unix_domain_socket) call on behalf of the sandbox, the server always sees a uid 0. Hence the server cannot authenticate the UDS requests coming from the sandbox.
Proposal
I propose to Add a new RPC
ConnectWithCreds
to allow gofer to connect to a unix domain socket with application's credentials. On that gofer server thread, the euid/egid are temporarily changed to application's uid/gid and restored after theconnect(2)
call.Questions
What do you think of this change? Is there any security/ functionality concern? Thank you so much for your feedback!