-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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: acquire privileges to access special files on windows #4994
Conversation
Ref: #4837 (comment) |
There might be files you forgot to commit, as I don't see where the list of files you mentioned are excluded. As for the windows specific privilege escalation, I would only apply it in the local exporter: buildkit/exporter/local/export.go Lines 173 to 176 in f9b730c
There is no need to do that in |
dadc834
to
a465895
Compare
// TODO: [discussion] wrapping this from the caller's side in buildkit | ||
// at the last point at session/filesync/diffcopy.go:25 | ||
// had no effect. Suspect is to do with the goroutines. | ||
return winio.RunWithPrivileges([]string{winio.SeBackupPrivilege}, func() error { |
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.
@gabriel-samfira -- so, I did manage to do for type=tar
but for local
, wrapping session/filesync/diffcopy.go:25
block didn't have any effect. Even tried separating out fsutil.Send(stream.Context(), stream, fs, progress)
alone, same.
Might you have any pointers? My hunch is that it's because the call breaks into goroutines and escapes the privilege binding?
buildkit/session/filesync/diffcopy.go
Line 25 in aebcc1f
return errors.WithStack(fsutil.Send(stream.Context(), stream, fs, progress)) |
I agree, would have been nice not to touch fsutil
.
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.
My hunch is that it's because the call breaks into goroutines and escapes the privilege binding?
I think that's indeed what's happening. The RunWithPrivileges
function locks the current thread for just the function that is about to run, then escalates privileges. At the end it releases the thread and restores previous privileges.
If the execution happens in another thread, that thread won't have the same privileges.
One more heavy handed way to do this is to try to escalate privileges process-wide using:
something like
winio.EnableProcessPrivileges([]string{winio.SeBackupPrivilege})
defer winio.DisableProcessPrivileges([]string{winio.SeBackupPrivilege})
// do the thing
Enabling process wide privileges is not ideal if it's being done in multiple places of the code base. There is a chance (I am not vastly familiar with internals) that if you revoke the privilege once you are done in a defer
, you may remove the privilege, while it's needed by some other go routine somewhere else in the code.
There is one other place that EnableProcessPrivilege
is used in fsutil
, here:
That can actually be converted to RunWithPrivileges
as it only sets the security descriptor on a file and can run in the same thread. But my point is that enabling/disabling privileges process wide needs to be done carefully. And we need to be aware of the potential hard to debug scenarios when something fails intermittently without obvious reason.
Adding this to fsutil
might make sense, but it feels equally heavy handed to require elevated privileges for every Walk()
, even when it's called for paths that we should have access to normally. The fsutil
package is generic. The case we're trying to address here is specific to the particular need we have here.
@tonistiigi what are your thoughts here?
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.
Thanks for that. Sure, I agree we need caution for process-wide escalation.
// at the last point at session/filesync/diffcopy.go:25 | ||
// had no effect. Suspect is to do with the goroutines. | ||
return winio.RunWithPrivileges([]string{winio.SeBackupPrivilege}, func() error { | ||
return s.walk(ctx) |
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.
Then as for the file skipping, also this needed to be at the place walking is happening, which is in fsutil
; I though of leaving that out so not to pollute the fsutil
too much?
Right now those metadata files are being exported which I think it's okay, to have the end user deal with the files as they so wish?
Directory: C:\dev\tmp\sample-1
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 5/8/2021 9:43 AM ProgramData
d---- 5/31/2024 4:36 PM System Volume Information <----
d---- 5/10/2024 11:17 PM Users
d---- 6/7/2024 10:44 AM WcSandboxState <----
d---- 5/10/2024 11:17 PM Windows
-a--- 6/6/2024 12:44 PM 97 hello.txt
-a--- 5/10/2024 11:14 PM 5647 License.txt
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.
The WcSandboxState
should be skipped. It gets created by the host OS when mounting layers. It is of no use to users.
It may be worth asking the server team about this.
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.
Sure, I can add that the exclusion, the team was okay with skipping that, was listed among what's skipped in their layer exports:
"\\System Volume Information",
"\\ProgramData\\Microsoft\\Diagnosis",
"\\WcSandboxState",
Do you suggest adding that in the fsutil
side or sending it from the caller?
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.
sending it from the caller makes more sense. If fsutil allows setting an exclusion list, that would be great.
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.
opened a separate issue for that here #5011
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.
recalling my approval, I didn't notice PR is still in draft mode....
2a25c5b
to
8ab986d
Compare
8ab986d
to
7ae3211
Compare
TODO: need to cross-check that there is no way the SeBackupPrivilege can be abused/exploited. WIP: how best to handle the files to be exclused without touching `fsutil` Signed-off-by: Anthony Nandaa <profnandaa@gmail.com>
7ae3211
to
e7ceb63
Compare
@gabriel-samfira @tonistiigi PTAL, also updated the PR description. |
Depends on moby#4994 Partial fix for moby#4485 Starting off with this one as a POC on the approach, before we proceed to complete the rest under `/frontend/dockerfile`. Tests covered so far: - [x] `/frontend/dockerfile: testEnvEmptyFormatting` - [x] `/frontend/dockerfile: testDockerignoreOverride` - [x] `/frontend/dockerfile: caseEmptyDestDir` Signed-off-by: Anthony Nandaa (from Dev Box) <profnandaa@gmail.com>
Depends on moby#4994 Partial fix for moby#4485 Starting off with this one as a POC on the approach, before we proceed to complete the rest under `/frontend/dockerfile`. Tests covered so far: - [x] `/frontend/dockerfile: testEnvEmptyFormatting` - [x] `/frontend/dockerfile: testDockerignoreOverride` - [x] `/frontend/dockerfile: caseEmptyDestDir` Signed-off-by: Anthony Nandaa <profnandaa@gmail.com>
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.
With the caveat that I already mentioned, this looks ok.
@tonistiigi @thompson-shaun -- moved it to milestone |
fixes #4985
Windows has some special / metadata files that need special privileges to access, even if the process is running as Admin.
Some of those files (across
nanoserver
andservercore
) currently are:Additionally, we have directories that don't need to be exported, I have separated that work in a separate issue here #5011
Also, I'm currently working on enabling the skipped integration tests on Windows, and most of them are using local exporter, therefore will be depending on this change e.g.:
buildkit/frontend/dockerfile/dockerfile_test.go
Lines 348 to 359 in eed17a4
--
Sample Test
Before:
After fix: