feat: use process wrapper for dropping capabilities

Use process wrapper introduced in #6814 to drop capabilities. This change
also means the capabilities are dropped per process level and not for
PID 1 (machined), which allows us to drop capabilities per process.

Signed-off-by: Noel Georgi <git@frezbo.dev>
This commit is contained in:
Noel Georgi 2023-02-06 16:21:45 +05:30
parent 0c6c888745
commit cc6e37a47f
No known key found for this signature in database
GPG Key ID: 21A9F444075C9E36
9 changed files with 25 additions and 53 deletions

View File

@ -81,7 +81,6 @@ func (*Sequencer) Initialize(r runtime.Runtime) []runtime.Phase {
MountCgroups,
MountPseudoFilesystems,
SetRLimit,
DropCapabilities,
).Append(
"integrity",
WriteIMAPolicy,

View File

@ -42,7 +42,6 @@ import (
clientv3 "go.etcd.io/etcd/client/v3"
"golang.org/x/sys/unix"
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
"kernel.org/pub/linux/libs/security/libcap/cap"
installer "github.com/siderolabs/talos/cmd/installer/pkg/install"
"github.com/siderolabs/talos/internal/app/machined/pkg/runtime"
@ -295,39 +294,6 @@ 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 {
prop, err := krnl.ReadParam(&kernel.Param{Key: "proc.sys.kernel.kexec_load_disabled"})
if v := strings.TrimSpace(string(prop)); err == nil && v != "0" {
logger.Printf("kernel.kexec_load_disabled is %v, skipping dropping capabilities", v)
return nil
}
// 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
@ -1270,20 +1236,6 @@ func injectCRIConfigPatch(ctx context.Context, st state.State, content []byte) e
return err
}
//nolint:deadcode,unused
func doesNotExists(p string) (err error) {
_, err = os.Stat(p)
if err != nil {
if os.IsNotExist(err) {
return nil
}
return err
}
return fmt.Errorf("file exists")
}
func existsAndIsFile(p string) (err error) {
var info os.FileInfo

View File

@ -13,6 +13,7 @@ import (
"github.com/containerd/containerd"
"github.com/containerd/containerd/oci"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/siderolabs/gen/maps"
"github.com/siderolabs/talos/internal/app/machined/pkg/runtime"
"github.com/siderolabs/talos/internal/app/machined/pkg/runtime/logging"
@ -167,9 +168,9 @@ func WithCustomSeccompProfile(override func(*specs.LinuxSeccomp)) Option {
}
}
// WithBoundedCapabilities sets the list of capabilities to drop.
func WithBoundedCapabilities(caps []string) Option {
// WithDroppedCapabilities sets the list of capabilities to drop.
func WithDroppedCapabilities(caps map[string]struct{}) Option {
return func(args *Options) {
args.DroppedCapabilities = caps
args.DroppedCapabilities = maps.Keys(caps)
}
}

View File

@ -114,6 +114,7 @@ func (c *Containerd) Runner(r runtime.Runtime) (runner.Runner, error) {
runner.WithEnv(env),
runner.WithOOMScoreAdj(-999),
runner.WithCgroupPath(constants.CgroupSystemRuntime),
runner.WithDroppedCapabilities(constants.DefaultDroppedCapabilities),
),
restart.WithType(restart.Forever),
), nil

View File

@ -105,6 +105,7 @@ func (c *CRI) Runner(r runtime.Runtime) (runner.Runner, error) {
runner.WithEnv(env),
runner.WithOOMScoreAdj(-500),
runner.WithCgroupPath(constants.CgroupPodRuntime),
runner.WithDroppedCapabilities(constants.DefaultDroppedCapabilities),
),
restart.WithType(restart.Forever),
), nil

View File

@ -84,6 +84,7 @@ func (c *Udevd) Runner(r runtime.Runtime) (runner.Runner, error) {
runner.WithLoggingManager(r.Logging()),
runner.WithEnv(env),
runner.WithCgroupPath(constants.CgroupSystemRuntime),
runner.WithDroppedCapabilities(constants.DefaultDroppedCapabilities),
),
restart.WithType(restart.Forever),
), nil

View File

@ -18,7 +18,9 @@ import (
"golang.org/x/sys/unix"
"kernel.org/pub/linux/libs/security/libcap/cap"
krnl "github.com/siderolabs/talos/pkg/kernel"
"github.com/siderolabs/talos/pkg/machinery/constants"
"github.com/siderolabs/talos/pkg/machinery/kernel"
)
var (
@ -70,7 +72,10 @@ func Main() {
}
}
if droppedCaps != "" {
prop, err := krnl.ReadParam(&kernel.Param{Key: "proc.sys.kernel.kexec_load_disabled"})
if v := strings.TrimSpace(string(prop)); err == nil && v != "0" {
log.Printf("kernel.kexec_load_disabled is %v, skipping dropping capabilities", v)
} else if droppedCaps != "" {
caps := strings.Split(droppedCaps, ",")
dropCaps := slices.Map(caps, func(c string) cap.Value {
capability, err := cap.FromName(c)

View File

@ -9,6 +9,8 @@ import (
"strings"
"kernel.org/pub/linux/libs/security/libcap/cap"
"github.com/siderolabs/talos/pkg/machinery/constants"
)
// AllGrantableCapabilities returns list of capabilities that can be granted to the container based on
@ -18,6 +20,10 @@ func AllGrantableCapabilities() []string {
for v := cap.Value(0); v < cap.MaxBits(); v++ {
if set, _ := cap.GetBound(v); set { //nolint:errcheck
if _, ok := constants.DefaultDroppedCapabilities[v.String()]; ok {
continue
}
capabilities = append(capabilities, strings.ToUpper(v.String()))
}
}

View File

@ -817,3 +817,9 @@ var Overlays = []string{
"/usr/etc/udev",
"/opt",
}
// DefaultDroppedCapabilities is the default set of capabilities to drop.
var DefaultDroppedCapabilities = map[string]struct{}{
"cap_sys_boot": {},
"cap_sys_module": {},
}