-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: x/sys/windows: indicate when ERROR_NOT_ALL_ASSIGNED occurs in AdjustTokenPrivileges #64170
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
Comments
CC @golang/windows |
I am not an expert in Windows security, but only mentions ERROR_NOT_ALL_ASSIGNED when SE_PRIVILEGE_REMOVED parameter is used. So perhaps your reasoning is wrong. I suggest you ask your question somewhere else where you can find at least some Windows security experts. I doubt many experts read your question here. You can try https://github.com/golang/go/wiki/Questions or https://stackoverflow.com Alex |
Thanks for taking the time to check and explain the issue.
Believe me, it does occur when
As you see the Windows function call can indicate success, even when As for a solution to my problem, I didn't feel the need to ask around as I already knew exactly what was happening. I already worked around the problem by calling the Windows API directly using I wanted it fixed so that others don't face the same issue. I thought of actually fixing the code myself and submitting a pull request, but I was discouraged by having to create a Gerrit account then going through several steps, and I also didn't have enough time to setup an environment on my local machine where I can build the source and run tests as it required installing some stuff and changing some git settings that may affect my other work, so I needed to setup a VM specifically for that. In short it was a long process for just updating 2-3 lines of code for something that could be rejected as it is a breaking change and I didn't have time. I also realize that this is a niche scenario, and not a lot of developers are affected by it. |
It is also fine just to point to the problem in the code, and perhaps others will be willing to implement the fix. Alex |
You are right. original code (for some reason this is different from the code on this repo) func AdjustTokenPrivileges(token Token, disableAllPrivileges bool, newstate *Tokenprivileges, buflen uint32, prevstate *Tokenprivileges, returnlen *uint32) (err error) {
var _p0 uint32
if disableAllPrivileges {
_p0 = 1
}
r1, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen)))
if r1 == 0 {
err = errnoErr(e1)
}
return
} suggested fix: This is what I would do to fix: func AdjustTokenPrivileges(token Token, disableAllPrivileges bool, newstate *Tokenprivileges, buflen uint32, prevstate *Tokenprivileges, returnlen *uint32) (err error) {
var _p0 uint32
if disableAllPrivileges {
_p0 = 1
}
r1, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen)))
if r1 == 0 || e1 == ERROR_NOT_ALL_ASSIGNED { // <-- additional check here.
err = errnoErr(e1)
}
return
} |
Change https://go.dev/cl/566036 mentions this issue: |
I've submitted CL 566036 which contains the fix proposed by @sherif-elmetainy. The problem I now see is that this is a breaking change. For example, the following code from https://github.com/Azure/azure-storage-azcopy would no longer report a useful error, at it is a shame because it is trying to sidestep our err = windows.AdjustTokenPrivileges(procToken, false, &tokenPrivs, oldPrivsSize, &oldPrivs, &requiredReturnLen)
if err != nil {
return err
}
if oldPrivs.PrivilegeCount != 1 {
// Only the successful changes are returned in the old state
// If there were none, that means it didn't work
return errors.New("could not activate '" + BackupModeFlagName + "' mode. Probably the account running AzCopy does not have " +
privName + " so AzCopy could not activate that privilege. Administrators usually have that privilege, but only when they are in an elevated command prompt. " +
"Members of the 'Backup Operators' security group also have that privilege. To check which privileges an account has, run this from a command line: whoami /priv")
} There are many other err = windows.AdjustTokenPrivileges(token, false, &tokenPrivs, 1024, nil, nil)
if err != nil || windows.GetLastError() != nil {
return false
} |
@bcmills suggested a few solutions to this issue in https://go-review.googlesource.com/c/sys/+/566036/comment/3e705da4_cddd965a/:
|
I would lean towards having a new API (option 2 in previous comment): // AdjustTokenPrivileges2 enables or disables privileges in the specified token
// by calling AdjustTokenPrivileges.
// Note that err can be [ERROR_NOT_ALL_ASSIGNED] even if success is true,
// which means that one or more privileges were not adjusted.
func AdjustTokenPrivileges2(...) (success bool, err error) I would also deprecate |
@qmuntal what would your proposed new I would go for
solution instead. Perhaps I don't understand the problem, but this is how Alex |
The function designed by Microsoft returns a bool in addition to the to the error value returned from |
Maybe? But I'm not sure from the documentation whether it is ever possible to get err := windows.AdjustTokenPrivileges(…)
switch err {
case nil:
// Adjusted all specified privileges.
case windows.ERROR_NOT_ALL_ASSIGNED:
// Partial success, but “[t]he token does not have one or more of the privileges
// specified in the NewState parameter.”
default:
// Failure.
return err
} That is: maybe the |
Could be, but this assumption is not written in the
Like in here: https://go-review.googlesource.com/c/sys/+/566036 |
Do you have a repro that demonstrates the problem with the current Go implementation of the If you do not have, then I would not vote for implementing Perhaps Go implementation does not match Microsoft documentation. But as long as users programs are not broken in any way, why change anything?
Your https://go-review.googlesource.com/c/sys/+/566036 change does not contain Thank you. Alex |
The issue description contains a reproducer. When running as no-admin, CL 566036 also contains a test case that fails with the current Go implementation.
The point is that programs that use |
Thanks for the test case. I was able to reproduce the problem. I agree with your suggestion to add
Alex |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes, it reproduces with the latest release as of 15 Nov 2023.
What operating system and processor architecture are you using (
go env
)?Windows 11 Pro Version 22H2 (OS Build 22621.2715)
go env
OutputWhat did you do?
Here is link to Go Playground (but note that this will not run on the Go Playground because it requires Windows environment). I also provided a full listing below.
https://go.dev/play/p/G2J2te4l-4q
The program is attempting to call
AdjustTokenPrivileges
to enable theSeSecurityPrivilege
. When I run the program elevated (as Administrator), the program runs as expected without an issue. The issue occurs when running as a normal user (non elevated privilege) where it also completes without any error, where it was supposed to panic at line 32.What did you expect to see?
When I run the program as a normal user (not administrator), I expect the
windows.AdjustTokenPrivileges
call at line 29 to fail with and return errorERROR_NOT_ALL_ASSIGNED
error, since the privilege that was requested to be enable was not enabled.What did you see instead?
windows.AdjustTokenPrivileges
returns null instead of returning an error.The text was updated successfully, but these errors were encountered: