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

proposal: x/sys/windows: allow specifying Security Capabilities in SysProcAttr #65611

Open
tgross opened this issue Feb 8, 2024 · 4 comments

Comments

@tgross
Copy link

tgross commented Feb 8, 2024

Proposal Details

Allow adding Security Capabilities to SysProcAttr on Windows. Note this is separate from the existing SecurityAttributes struct which can be set as the ProcessAttributes or ThreadAttributes field.

Motivation

Recently as part of work to sandbox a subprocess, the Nomad team at HashiCorp needed to add a SECURITY_CAPABILITIES struct to the StartupInfoEx for a process. Because this is not exposed in SysProcAttr this involved writing an unfortunate amount of code, much of which had to be simply lifted from the os/exec stdlib. See helper/winexec/create.go

Implementation Notes

Previously a proposal was implemented to add a ParentProcess field to SysProcAttr for Windows #44011. This was discussed around the same time as a rejected proposal to add the full StartupInfoEx struct #44005.

One of the reasons why the StartupInfoEx proposal was rejected was because it resulted in ambiguity around how one would merge any default attributes with ones provided by the user. There are two options to work around this:

Option 1: Extensible

Our implementation referenced above adds a ProcThreadAttributes field to the forked os/exec.Cmd which is a slice of ProcThreadAttribute. This instead could be added to SysProcAttr as an extensible way of adding more attributes:

type SysProcAttr struct {
    // ...
    ProcThreadAttributes []ProcThreadAttribute
}

type ProcThreadAttribute struct {
	Attribute uintptr
	Value     unsafe.Pointer
	Size      uintptr
}

When the StartupInfoEx struct is built, we call newProcThreadAttributeList with a count of len(ProcThreadAttributes) + 2 (taking the default attributes from syscall/exec_windows.go). Any ProcThreadAttributes that come from the user override those defaults if using the same Attribute field, which makes for unambiguous behavior.

Option 2: SecurityAttributes only

An alternative would be to add a SecurityCapabilities field to SysProcAttr and

type SysProcAttr struct {
    // ...
    SecurityCapabilities SecurityCapabilities
}

type SecurityCapabilities struct {
	AppContainerSid uintptr // PSID *windows.SID
	Capabilities    uintptr // SID_AND_ATTRIBUTES *windows.SIDAndAttributes
	CapabilityCount uint32
	Reserved        uint32
}

It would then be up to syscall/exec_windows.go to create the appropriate attributes for StartupInfoEx, as we do already for the parent handle, etc.

@tgross tgross added the Proposal label Feb 8, 2024
@gopherbot gopherbot added this to the Proposal milestone Feb 8, 2024
@ianlancetaylor
Copy link
Contributor

CC @golang/windows

@qmuntal
Copy link
Contributor

qmuntal commented Feb 20, 2024

Thanks for submitting this proposal. IMO supporting security capabilities would be a good addition.

Some comments:

The concern in #44005 was that attributes set by the user could conflict with parameters and attributes set by syscall.StartProcess, and some conflicts might not be possible to reconcile. The conclusion was that we want to curate which attributes are allowed to be set by the user so syscall.StartProcess is always coherent. This discards the option 1.

An alternative would be to add a SecurityCapabilities field to SysProcAttr and

This seems like the way to go. All new types and properties should be defined in the syscall package, not in x/sys/windows, as it is what os/exec uses under the hood. I've modified a bit your proposed API to fit better in syscall:

package syscall

type SecurityCapabilities struct {
	AppContainerSid *SID
	Capabilities    *SIDAndAttributes
	CapabilityCount uint32
	Reserved        uint32
}

type SysProcAttr struct {
	...
	SecurityCapabilities       *SecurityCapabilities // if set, applies these security capabilities to the new process
}

@tgross
Copy link
Author

tgross commented Feb 26, 2024

Makes sense to me! I should have noted in the original proposal that I/we are happy to contribute this patch. What's the next step at this point? Should we submit the patch along the lines above or should we submit a design doc?

@qmuntal
Copy link
Contributor

qmuntal commented Mar 7, 2024

Makes sense to me! I should have noted in the original proposal that I/we are happy to contribute this patch. What's the next step at this point? Should we submit the patch along the lines above or should we submit a design doc?

We need to wait for this proposal to be discussed by the proposal committee, see the-proposal-process. There is no need for a design doc, the changes are simple enough. I would recommend holding your patch till the proposal is approved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Incoming
Development

No branches or pull requests

4 participants