youtubebeat/vendor/github.com/elastic/beats/libbeat/common/seccomp/seccomp.go

136 lines
3.7 KiB
Go

// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package seccomp
import (
"runtime"
"github.com/pkg/errors"
"github.com/elastic/beats/libbeat/common"
"github.com/elastic/beats/libbeat/logp"
"github.com/elastic/go-seccomp-bpf"
)
var (
defaultPolicy *seccomp.Policy
registeredPolicy *seccomp.Policy
)
// MustRegisterPolicy registers a seccomp policy to use instead of the default
// policy. This can be used to register an application specific seccomp policy
// that is tailored to the specific system calls that the application requires.
// It panics if a policy has already been registered or if the given policy
// is invalid.
func MustRegisterPolicy(p *seccomp.Policy) {
if p == nil {
panic(errors.New("seccomp policy cannot be nil"))
}
if registeredPolicy != nil {
panic(errors.New("a seccomp policy is already registered"))
}
// Ensure that the policy is valid and usable.
if _, err := p.Assemble(); err != nil {
panic(errors.Wrap(err, "failed to register seccomp policy"))
}
registeredPolicy = p
}
// LoadFilter loads a seccomp system call filter into the kernel for this
// process. This feature is only available on Linux 3.17+. If c is nil or does
// not contain a seccomp policy then a default policy will be used.
//
// An error is returned if there is a config validation problem. Otherwise any
// errors interfacing with the kernel are logged (i.e. it is non-fatal if
// seccomp cannot be setup).
//
// Policy precedence order (highest to lowest):
// - Policy values from config
// - Application registered policy
// - Default policy (a simple blacklist)
func LoadFilter(c *common.Config) error {
// Bail out if seccomp.enabled=false.
if c != nil && !c.Enabled() {
return nil
}
p, err := getPolicy(c)
if err != nil {
return err
}
loadFilter(p)
return nil
}
// loadFilter loads a system call filter.
func loadFilter(p *seccomp.Policy) {
log := logp.NewLogger("seccomp")
if runtime.GOOS != "linux" {
log.Debug("Syscall filtering is only supported on Linux")
return
}
if !seccomp.Supported() {
log.Info("Syscall filter could not be installed because the kernel " +
"does not support seccomp")
return
}
if p == nil {
log.Debug("No seccomp policy is defined")
return
}
filter := seccomp.Filter{
NoNewPrivs: true,
Flag: seccomp.FilterFlagTSync,
Policy: *p,
}
log.Debugw("Loading syscall filter", "seccomp_filter", filter)
if err := seccomp.LoadFilter(filter); err != nil {
log.Warn("Syscall filter could not be installed", "error", err,
"seccomp_filter", filter)
return
}
log.Infow("Syscall filter successfully installed")
}
func getPolicy(c *common.Config) (*seccomp.Policy, error) {
policy := defaultPolicy
if registeredPolicy != nil {
policy = registeredPolicy
}
if c != nil && (c.HasField("default_action") || c.HasField("syscalls")) {
if policy == nil {
policy = &seccomp.Policy{}
}
if err := c.Unpack(policy); err != nil {
return nil, err
}
}
return policy, nil
}