Skip to content

Commit

Permalink
feat: drop some capabilities to be never available
Browse files Browse the repository at this point in the history
This PR makes sure that some capabilities (SYS_BOOT and SYS_MODULES) and
never be gained by any process running on Talos except for `machined`
itself.

Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
  • Loading branch information
smira committed Sep 8, 2021
1 parent 51e9836 commit 69897db
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 3 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,5 @@ require (
k8s.io/cri-api v0.22.1
k8s.io/kubectl v0.22.1
k8s.io/kubelet v0.22.1
kernel.org/pub/linux/libs/security/libcap/cap v1.2.56
)
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1893,6 +1893,10 @@ k8s.io/metrics v0.22.1/go.mod h1:i/ZNap89UkV1gLa26dn7fhKAdheJaKy+moOqJbiif7E=
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9 h1:imL9YgXQ9p7xmPzHFm/vVd/cF78jad+n4wK1ABwYtMM=
k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
kernel.org/pub/linux/libs/security/libcap/cap v1.2.56 h1:nwsOaUtqOMtPPPOwnG90fV8EhVFxj81g7acKMfM/2ag=
kernel.org/pub/linux/libs/security/libcap/cap v1.2.56/go.mod h1:zOKBqiVovj7YgbAvwDRPp1xVaV2PiDoklW2YG8xmzDY=
kernel.org/pub/linux/libs/security/libcap/psx v1.2.56 h1:yAcMQY+fGwpA0puwASaxk+gwlbjrl8TIroSpw8zL4Zo=
kernel.org/pub/linux/libs/security/libcap/psx v1.2.56/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
Expand Down
10 changes: 9 additions & 1 deletion internal/app/machined/internal/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
containerdrunner "github.com/talos-systems/talos/internal/app/machined/pkg/system/runner/containerd"
"github.com/talos-systems/talos/internal/pkg/capability"
"github.com/talos-systems/talos/internal/pkg/containers/image"
machineapi "github.com/talos-systems/talos/pkg/machinery/api/machine"
"github.com/talos-systems/talos/pkg/machinery/config"
Expand Down Expand Up @@ -113,7 +114,14 @@ func RunInstallerContainer(disk, platform, ref string, configBytes []byte, reg c
oci.WithHostHostsFile,
oci.WithHostResolvconf,
oci.WithParentCgroupDevices,
oci.WithPrivileged,
oci.WithCapabilities(capability.AllGrantableCapabilities()),
oci.WithMaskedPaths(nil),
oci.WithReadonlyPaths(nil),
oci.WithWriteableSysfs,
oci.WithWriteableCgroupfs,
oci.WithSelinuxLabel(""),
oci.WithApparmorProfile(""),
oci.WithSeccompUnconfined,
oci.WithAllDevicesAllowed,
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ func (*Sequencer) Initialize(r runtime.Runtime) []runtime.Phase {
MountCgroups,
MountPseudoFilesystems,
SetRLimit,
DropCapabilities,
).Append(
"integrity",
WriteIMAPolicy,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
clientv3 "go.etcd.io/etcd/client/v3"
"golang.org/x/sys/unix"
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
"kernel.org/pub/linux/libs/security/libcap/cap"

installer "github.com/talos-systems/talos/cmd/installer/pkg/install"
"github.com/talos-systems/talos/internal/app/machined/internal/install"
Expand Down Expand Up @@ -237,6 +238,51 @@ func SetRLimit(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFun
}, "setRLimit"
}

// DropCapabilities drops some capabilities so that they can't be restored by child processes.
func DropCapabilities(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc, string) {
return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) error {
// Disallow raising ambient capabilities (ever).
secbits := cap.GetSecbits()
secbits |=
cap.SecbitNoCapAmbientRaise | cap.SecbitNoCapAmbientRaiseLocked

if err := secbits.Set(); err != nil {
return fmt.Errorf("error setting secbits: %w", err)
}

// Set PR_SET_NO_NEW_PRIVS to limit setuid and similar privilege raising techniques.
// See https://www.kernel.org/doc/html/v5.10/userspace-api/no_new_privs.html.
if _, _, err := syscall.AllThreadsSyscall6(syscall.SYS_PRCTL, unix.PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0, 0); err != 0 {
if errors.Is(err, syscall.EOPNOTSUPP) {
logger.Printf("no_new_privs skipped, as Talos is built with CGo")
} else {
return fmt.Errorf("error setting no new privs: %w", err)
}
}

// Drop capabilities from the bounding set effectively disabling it for all forked processes,
// but keep them for PID 1.
droppedCapabilities := []cap.Value{
cap.SYS_BOOT,
cap.SYS_MODULE,
}

iab := cap.IABGetProc()

for _, val := range droppedCapabilities {
if err := iab.SetVector(cap.Bound, true, val); err != nil {
return fmt.Errorf("error removing %s from the bounding set: %w", val, err)
}
}

if err := iab.SetProc(); err != nil {
return fmt.Errorf("error applying caps: %w", err)
}

return nil
}, "dropCapabilities"
}

// See https://www.kernel.org/doc/Documentation/ABI/testing/ima_policy
var rules = []string{
"dont_measure fsmagic=0x9fa0", // PROC_SUPER_MAGIC
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,6 @@ func (c *containerdRunner) newOCISpecOpts(image oci.Image) []oci.SpecOpts {
oci.WithHostHostsFile,
oci.WithHostResolvconf,
oci.WithNoNewPrivileges,
seccomp.WithDefaultProfile(),
)

if c.opts.CgroupPath != "" {
Expand All @@ -290,6 +289,10 @@ func (c *containerdRunner) newOCISpecOpts(image oci.Image) []oci.SpecOpts {
c.opts.OCISpecOpts...,
)

specOpts = append(specOpts,
seccomp.WithDefaultProfile(), // add seccomp profile last, as it depends on process capabilities
)

return specOpts
}

Expand Down
9 changes: 8 additions & 1 deletion internal/app/machined/pkg/system/services/kubelet.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/talos-systems/talos/internal/app/machined/pkg/system/runner"
"github.com/talos-systems/talos/internal/app/machined/pkg/system/runner/containerd"
"github.com/talos-systems/talos/internal/app/machined/pkg/system/runner/restart"
"github.com/talos-systems/talos/internal/pkg/capability"
"github.com/talos-systems/talos/internal/pkg/containers/image"
"github.com/talos-systems/talos/pkg/argsbuilder"
"github.com/talos-systems/talos/pkg/conditions"
Expand Down Expand Up @@ -200,8 +201,14 @@ func (k *Kubelet) Runner(r runtime.Runtime) (runner.Runner, error) {
oci.WithHostNamespace(specs.NetworkNamespace),
oci.WithHostNamespace(specs.PIDNamespace),
oci.WithParentCgroupDevices,
oci.WithPrivileged,
oci.WithMaskedPaths(nil),
oci.WithReadonlyPaths(nil),
oci.WithWriteableSysfs,
oci.WithWriteableCgroupfs,
oci.WithSelinuxLabel(""),
oci.WithApparmorProfile(""),
oci.WithAllDevicesAllowed,
oci.WithCapabilities(capability.AllGrantableCapabilities()), // TODO: kubelet doesn't need all of these, we should consider limiting capabilities
),
),
restart.WithType(restart.Forever),
Expand Down
26 changes: 26 additions & 0 deletions internal/pkg/capability/capability.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Package capability provides utility functions to work with capabilities.
package capability

import (
"strings"

"kernel.org/pub/linux/libs/security/libcap/cap"
)

// AllGrantableCapabilities returns list of capabilities that can be granted to the container based on
// process bounding capabilities.
func AllGrantableCapabilities() []string {
capabilities := []string{}

for v := cap.Value(0); v < cap.MaxBits(); v++ {
if set, _ := cap.GetBound(v); set { //nolint:errcheck
capabilities = append(capabilities, strings.ToUpper(v.String()))
}
}

return capabilities
}

0 comments on commit 69897db

Please sign in to comment.