mirror of https://github.com/docker/cli.git
Merge 446d4138ed
into 81401f37f2
This commit is contained in:
commit
40b80b679a
|
@ -26,7 +26,7 @@ require (
|
|||
github.com/mattn/go-runewidth v0.0.15
|
||||
github.com/moby/patternmatcher v0.6.0
|
||||
github.com/moby/swarmkit/v2 v2.0.0-20241017191044-e8ecf83ee08e
|
||||
github.com/moby/sys/capability v0.3.0
|
||||
github.com/moby/sys/capability v0.4.0
|
||||
github.com/moby/sys/sequential v0.6.0
|
||||
github.com/moby/sys/signal v0.7.1
|
||||
github.com/moby/term v0.5.0
|
||||
|
|
|
@ -168,8 +168,8 @@ github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkV
|
|||
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||
github.com/moby/swarmkit/v2 v2.0.0-20241017191044-e8ecf83ee08e h1:1yC8fRqStY6NirU/swI74fsrHvZVMbtxsHcvl8YpzDg=
|
||||
github.com/moby/swarmkit/v2 v2.0.0-20241017191044-e8ecf83ee08e/go.mod h1:mTTGIAz/59OGZR5Qe+QByIe3Nxc+sSuJkrsStFhr6Lg=
|
||||
github.com/moby/sys/capability v0.3.0 h1:kEP+y6te0gEXIaeQhIi0s7vKs/w0RPoH1qPa6jROcVg=
|
||||
github.com/moby/sys/capability v0.3.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=
|
||||
github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk=
|
||||
github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=
|
||||
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
|
||||
github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
|
||||
github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0=
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
[codespell]
|
||||
skip = ./.git
|
||||
ignore-words-list = nd
|
|
@ -1,6 +0,0 @@
|
|||
linters:
|
||||
enable:
|
||||
- unconvert
|
||||
- unparam
|
||||
- gofumpt
|
||||
- errorlint
|
|
@ -5,6 +5,30 @@ from https://github.com/syndtr/gocapability/commit/42c35b4376354fd5.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.4.0] - 2024-11-11
|
||||
|
||||
### Added
|
||||
* New separate API for ambient ([GetAmbient], [SetAmbient], [ResetAmbient])
|
||||
and bound ([GetBound], [DropBound]) capabilities, modelled after libcap. (#176)
|
||||
|
||||
### Fixed
|
||||
* [Apply] now returns an error if called for non-zero `pid`. Before this change,
|
||||
it could silently change some capabilities of the current process, instead of
|
||||
the one identified by the `pid`. (#168, #174)
|
||||
* Fixed tests that change capabilities to be run in a separate process. (#173)
|
||||
* Other improvements in tests. (#169, #170)
|
||||
|
||||
### Changed
|
||||
* Use raw syscalls (which are slightly faster). (#176)
|
||||
* Most tests are now limited to testing the public API of the package. (#162)
|
||||
* Simplify parsing /proc/*pid*/status, add a test case. (#162)
|
||||
* Optimize the number of syscall to set ambient capabilities in Apply
|
||||
by clearing them first; add a test case. (#163, #164)
|
||||
* Better documentation for [Apply], [NewFile], [NewFile2], [NewPid], [NewPid2]. (#175)
|
||||
|
||||
### Removed
|
||||
* `.golangci.yml` and `.codespellrc` are no longer part of the package. (#158)
|
||||
|
||||
## [0.3.0] - 2024-09-25
|
||||
|
||||
### Added
|
||||
|
@ -63,14 +87,24 @@ This is an initial release since the fork.
|
|||
* Removed init function so programs that use this package start faster. [#6]
|
||||
* Removed `CAP_LAST_CAP` (use [LastCap] instead). [#6]
|
||||
|
||||
<!-- Doc links. -->
|
||||
<!-- Doc links (please keep sorted). -->
|
||||
[Apply]: https://pkg.go.dev/github.com/moby/sys/capability#Capabilities.Apply
|
||||
[DropBound]: https://pkg.go.dev/github.com/moby/sys/capability#DropBound
|
||||
[GetAmbient]: https://pkg.go.dev/github.com/moby/sys/capability#GetAmbient
|
||||
[GetBound]: https://pkg.go.dev/github.com/moby/sys/capability#GetBound
|
||||
[LastCap]: https://pkg.go.dev/github.com/moby/sys/capability#LastCap
|
||||
[List]: https://pkg.go.dev/github.com/moby/sys/capability#List
|
||||
[ListKnown]: https://pkg.go.dev/github.com/moby/sys/capability#ListKnown
|
||||
[ListSupported]: https://pkg.go.dev/github.com/moby/sys/capability#ListSupported
|
||||
[List]: https://pkg.go.dev/github.com/moby/sys/capability#List
|
||||
[NewFile2]: https://pkg.go.dev/github.com/moby/sys/capability#NewFile2
|
||||
[NewFile]: https://pkg.go.dev/github.com/moby/sys/capability#NewFile
|
||||
[NewPid2]: https://pkg.go.dev/github.com/moby/sys/capability#NewPid2
|
||||
[NewPid]: https://pkg.go.dev/github.com/moby/sys/capability#NewPid
|
||||
[ResetAmbient]: https://pkg.go.dev/github.com/moby/sys/capability#ResetAmbient
|
||||
[SetAmbient]: https://pkg.go.dev/github.com/moby/sys/capability#SetAmbient
|
||||
|
||||
<!-- Minor releases. -->
|
||||
[0.4.0]: https://github.com/moby/sys/releases/tag/capability%2Fv0.4.0
|
||||
[0.3.0]: https://github.com/moby/sys/releases/tag/capability%2Fv0.3.0
|
||||
[0.2.0]: https://github.com/moby/sys/releases/tag/capability%2Fv0.2.0
|
||||
[0.1.1]: https://github.com/kolyshkin/capability/compare/v0.1.0...v0.1.1
|
||||
|
|
|
@ -56,16 +56,16 @@ type Capabilities interface {
|
|||
// outstanding changes.
|
||||
Load() error
|
||||
|
||||
// Apply apply the capabilities settings, so all changes will take
|
||||
// effect.
|
||||
// Apply apply the capabilities settings, so all changes made by
|
||||
// [Set], [Unset], [Fill], or [Clear] will take effect.
|
||||
Apply(kind CapType) error
|
||||
}
|
||||
|
||||
// NewPid initializes a new [Capabilities] object for given pid when
|
||||
// it is nonzero, or for the current process if pid is 0.
|
||||
//
|
||||
// Deprecated: Replace with [NewPid2] followed by [Capabilities.Load].
|
||||
// For example, replace:
|
||||
// Deprecated: replace with [NewPid2] followed by optional [Capabilities.Load]
|
||||
// (only if needed). For example, replace:
|
||||
//
|
||||
// c, err := NewPid(0)
|
||||
// if err != nil {
|
||||
|
@ -93,16 +93,16 @@ func NewPid(pid int) (Capabilities, error) {
|
|||
|
||||
// NewPid2 initializes a new [Capabilities] object for given pid when
|
||||
// it is nonzero, or for the current process if pid is 0. This
|
||||
// does not load the process's current capabilities; to do that you
|
||||
// must call [Capabilities.Load] explicitly.
|
||||
// does not load the process's current capabilities; if needed,
|
||||
// call [Capabilities.Load].
|
||||
func NewPid2(pid int) (Capabilities, error) {
|
||||
return newPid(pid)
|
||||
}
|
||||
|
||||
// NewFile initializes a new Capabilities object for given file path.
|
||||
//
|
||||
// Deprecated: Replace with [NewFile2] followed by [Capabilities.Load].
|
||||
// For example, replace:
|
||||
// Deprecated: replace with [NewFile2] followed by optional [Capabilities.Load]
|
||||
// (only if needed). For example, replace:
|
||||
//
|
||||
// c, err := NewFile(path)
|
||||
// if err != nil {
|
||||
|
@ -130,7 +130,7 @@ func NewFile(path string) (Capabilities, error) {
|
|||
|
||||
// NewFile2 creates a new initialized [Capabilities] object for given
|
||||
// file path. This does not load the process's current capabilities;
|
||||
// to do that you must call [Capabilities.Load] explicitly.
|
||||
// if needed, call [Capabilities.Load].
|
||||
func NewFile2(path string) (Capabilities, error) {
|
||||
return newFile(path)
|
||||
}
|
||||
|
@ -142,3 +142,35 @@ func NewFile2(path string) (Capabilities, error) {
|
|||
func LastCap() (Cap, error) {
|
||||
return lastCap()
|
||||
}
|
||||
|
||||
// GetAmbient determines if a specific ambient capability is raised in the
|
||||
// calling thread.
|
||||
func GetAmbient(c Cap) (bool, error) {
|
||||
return getAmbient(c)
|
||||
}
|
||||
|
||||
// SetAmbient raises or lowers specified ambient capabilities for the calling
|
||||
// thread. To complete successfully, the prevailing effective capability set
|
||||
// must have a raised CAP_SETPCAP. Further, to raise a specific ambient
|
||||
// capability the inheritable and permitted sets of the calling thread must
|
||||
// already contain the specified capability.
|
||||
func SetAmbient(raise bool, caps ...Cap) error {
|
||||
return setAmbient(raise, caps...)
|
||||
}
|
||||
|
||||
// ResetAmbient resets all of the ambient capabilities for the calling thread
|
||||
// to their lowered value.
|
||||
func ResetAmbient() error {
|
||||
return resetAmbient()
|
||||
}
|
||||
|
||||
// GetBound determines if a specific bounding capability is raised in the
|
||||
// calling thread.
|
||||
func GetBound(c Cap) (bool, error) {
|
||||
return getBound(c)
|
||||
}
|
||||
|
||||
// DropBound lowers the specified bounding set capability.
|
||||
func DropBound(caps ...Cap) error {
|
||||
return dropBound(caps...)
|
||||
}
|
||||
|
|
|
@ -117,6 +117,13 @@ func newPid(pid int) (c Capabilities, retErr error) {
|
|||
return
|
||||
}
|
||||
|
||||
func ignoreEINVAL(err error) error {
|
||||
if errors.Is(err, syscall.EINVAL) {
|
||||
err = nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type capsV3 struct {
|
||||
hdr capHeader
|
||||
data [2]capData
|
||||
|
@ -307,15 +314,15 @@ func (c *capsV3) Load() (err error) {
|
|||
}
|
||||
break
|
||||
}
|
||||
if strings.HasPrefix(line, "CapB") {
|
||||
_, err = fmt.Sscanf(line[4:], "nd: %08x%08x", &c.bounds[1], &c.bounds[0])
|
||||
if val, ok := strings.CutPrefix(line, "CapBnd:\t"); ok {
|
||||
_, err = fmt.Sscanf(val, "%08x%08x", &c.bounds[1], &c.bounds[0])
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "CapA") {
|
||||
_, err = fmt.Sscanf(line[4:], "mb: %08x%08x", &c.ambient[1], &c.ambient[0])
|
||||
if val, ok := strings.CutPrefix(line, "CapAmb:\t"); ok {
|
||||
_, err = fmt.Sscanf(val, "%08x%08x", &c.ambient[1], &c.ambient[0])
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
@ -327,7 +334,10 @@ func (c *capsV3) Load() (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (c *capsV3) Apply(kind CapType) (err error) {
|
||||
func (c *capsV3) Apply(kind CapType) error {
|
||||
if c.hdr.pid != 0 {
|
||||
return errors.New("unable to modify capabilities of another process")
|
||||
}
|
||||
last, err := LastCap()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -336,21 +346,17 @@ func (c *capsV3) Apply(kind CapType) (err error) {
|
|||
var data [2]capData
|
||||
err = capget(&c.hdr, &data[0])
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if (1<<uint(CAP_SETPCAP))&data[0].effective != 0 {
|
||||
for i := Cap(0); i <= last; i++ {
|
||||
if c.Get(BOUNDING, i) {
|
||||
continue
|
||||
}
|
||||
err = prctl(syscall.PR_CAPBSET_DROP, uintptr(i), 0, 0, 0)
|
||||
// Ignore EINVAL since the capability may not be supported in this system.
|
||||
err = ignoreEINVAL(dropBound(i))
|
||||
if err != nil {
|
||||
// Ignore EINVAL since the capability may not be supported in this system.
|
||||
if err == syscall.EINVAL { //nolint:errorlint // Errors from syscall are bare.
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
return
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -359,29 +365,73 @@ func (c *capsV3) Apply(kind CapType) (err error) {
|
|||
if kind&CAPS == CAPS {
|
||||
err = capset(&c.hdr, &c.data[0])
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if kind&AMBS == AMBS {
|
||||
// Ignore EINVAL as not supported on kernels before 4.3
|
||||
err = ignoreEINVAL(resetAmbient())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := Cap(0); i <= last; i++ {
|
||||
action := pr_CAP_AMBIENT_LOWER
|
||||
if c.Get(AMBIENT, i) {
|
||||
action = pr_CAP_AMBIENT_RAISE
|
||||
if !c.Get(AMBIENT, i) {
|
||||
continue
|
||||
}
|
||||
err = prctl(pr_CAP_AMBIENT, action, uintptr(i), 0, 0)
|
||||
// Ignore EINVAL as not supported on kernels before 4.3
|
||||
err = ignoreEINVAL(setAmbient(true, i))
|
||||
if err != nil {
|
||||
// Ignore EINVAL as not supported on kernels before 4.3
|
||||
if err == syscall.EINVAL { //nolint:errorlint // Errors from syscall are bare.
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
return
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
func getAmbient(c Cap) (bool, error) {
|
||||
res, err := prctlRetInt(pr_CAP_AMBIENT, pr_CAP_AMBIENT_IS_SET, uintptr(c))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return res > 0, nil
|
||||
}
|
||||
|
||||
func setAmbient(raise bool, caps ...Cap) error {
|
||||
op := pr_CAP_AMBIENT_RAISE
|
||||
if !raise {
|
||||
op = pr_CAP_AMBIENT_LOWER
|
||||
}
|
||||
for _, val := range caps {
|
||||
err := prctl(pr_CAP_AMBIENT, op, uintptr(val))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func resetAmbient() error {
|
||||
return prctl(pr_CAP_AMBIENT, pr_CAP_AMBIENT_CLEAR_ALL, 0)
|
||||
}
|
||||
|
||||
func getBound(c Cap) (bool, error) {
|
||||
res, err := prctlRetInt(syscall.PR_CAPBSET_READ, uintptr(c), 0)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return res > 0, nil
|
||||
}
|
||||
|
||||
func dropBound(caps ...Cap) error {
|
||||
for _, val := range caps {
|
||||
err := prctl(syscall.PR_CAPBSET_DROP, uintptr(val), 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newFile(path string) (c Capabilities, err error) {
|
||||
|
|
|
@ -24,3 +24,23 @@ func newFile(_ string) (Capabilities, error) {
|
|||
func lastCap() (Cap, error) {
|
||||
return -1, errNotSup
|
||||
}
|
||||
|
||||
func getAmbient(_ Cap) (bool, error) {
|
||||
return false, errNotSup
|
||||
}
|
||||
|
||||
func setAmbient(_ bool, _ ...Cap) error {
|
||||
return errNotSup
|
||||
}
|
||||
|
||||
func resetAmbient() error {
|
||||
return errNotSup
|
||||
}
|
||||
|
||||
func getBound(_ Cap) (bool, error) {
|
||||
return false, errNotSup
|
||||
}
|
||||
|
||||
func dropBound(_ ...Cap) error {
|
||||
return errNotSup
|
||||
}
|
||||
|
|
|
@ -316,7 +316,7 @@ func ListKnown() []Cap {
|
|||
return list()
|
||||
}
|
||||
|
||||
// ListSupported retuns the list of all capabilities known to the package,
|
||||
// ListSupported returns the list of all capabilities known to the package,
|
||||
// except those that are not supported by the currently running Linux kernel.
|
||||
func ListSupported() ([]Cap, error) {
|
||||
last, err := LastCap()
|
||||
|
|
|
@ -24,7 +24,7 @@ type capData struct {
|
|||
}
|
||||
|
||||
func capget(hdr *capHeader, data *capData) (err error) {
|
||||
_, _, e1 := syscall.Syscall(syscall.SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||
_, _, e1 := syscall.RawSyscall(syscall.SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ func capget(hdr *capHeader, data *capData) (err error) {
|
|||
}
|
||||
|
||||
func capset(hdr *capHeader, data *capData) (err error) {
|
||||
_, _, e1 := syscall.Syscall(syscall.SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||
_, _, e1 := syscall.RawSyscall(syscall.SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
}
|
||||
|
@ -48,14 +48,22 @@ const (
|
|||
pr_CAP_AMBIENT_CLEAR_ALL = uintptr(4)
|
||||
)
|
||||
|
||||
func prctl(option int, arg2, arg3, arg4, arg5 uintptr) (err error) {
|
||||
_, _, e1 := syscall.Syscall6(syscall.SYS_PRCTL, uintptr(option), arg2, arg3, arg4, arg5, 0)
|
||||
func prctl(option int, arg2, arg3 uintptr) (err error) {
|
||||
_, _, e1 := syscall.RawSyscall(syscall.SYS_PRCTL, uintptr(option), arg2, arg3)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func prctlRetInt(option int, arg2, arg3 uintptr) (int, error) {
|
||||
ret, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, uintptr(option), arg2, arg3)
|
||||
if err != 0 {
|
||||
return 0, err
|
||||
}
|
||||
return int(ret), nil
|
||||
}
|
||||
|
||||
const (
|
||||
vfsXattrName = "security.capability"
|
||||
|
||||
|
@ -92,7 +100,7 @@ func getVfsCap(path string, dest *vfscapData) (err error) {
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_vfsXattrName)), uintptr(unsafe.Pointer(dest)), vfscapDataSizeV2, 0, 0)
|
||||
r0, _, e1 := syscall.RawSyscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_vfsXattrName)), uintptr(unsafe.Pointer(dest)), vfscapDataSizeV2, 0, 0)
|
||||
if e1 != 0 {
|
||||
if e1 == syscall.ENODATA {
|
||||
dest.version = 2
|
||||
|
@ -145,7 +153,7 @@ func setVfsCap(path string, data *vfscapData) (err error) {
|
|||
} else {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
_, _, e1 := syscall.Syscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_vfsXattrName)), uintptr(unsafe.Pointer(data)), size, 0, 0)
|
||||
_, _, e1 := syscall.RawSyscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_vfsXattrName)), uintptr(unsafe.Pointer(data)), size, 0, 0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
}
|
||||
|
|
|
@ -205,7 +205,7 @@ github.com/moby/swarmkit/v2/api/defaults
|
|||
github.com/moby/swarmkit/v2/api/genericresource
|
||||
github.com/moby/swarmkit/v2/manager/raftselector
|
||||
github.com/moby/swarmkit/v2/protobuf/plugin
|
||||
# github.com/moby/sys/capability v0.3.0
|
||||
# github.com/moby/sys/capability v0.4.0
|
||||
## explicit; go 1.21
|
||||
github.com/moby/sys/capability
|
||||
# github.com/moby/sys/sequential v0.6.0
|
||||
|
|
Loading…
Reference in New Issue