Files
Etienne PerotandgVisor bot 8d1cd3dbae seccomp: Refactor to allow arbitrary number of RuleSets.
This is meant to make #12557 possible to implement, i.e.
making it possible for the seccomp configuration to specify actions
other than deny/allow in the main `runsc` configuration. This change
doesn't do that but it adds the structures to make that possible.

PiperOrigin-RevId: 868246148
2026-02-10 11:41:43 -08:00

101 lines
3.1 KiB
Go

// Copyright 2023 The gVisor Authors.
//
// Licensed 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 example defines two seccomp programs ("example_program1" and
// "example_program2") to be embedded in the `usage` package in this
// directory.
package example
import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/seccomp"
"gvisor.dev/gvisor/pkg/seccomp/precompiledseccomp"
)
// Variable names used in the precompiled programs.
// In this example, we have two file descriptors, which fit in 32 bits.
// If you need a 64-bit variable, simply declare two 32-bit variables and
// concatenate them to a single 64-bit number in the function that
// generates the `seccomp.Program`.
const (
FD1 = "fd1"
FD2 = "fd2"
)
// Name of the example programs.
const (
// Program1Name is the name of the first example program.
// It allows reading from `FD1` and `FD2`, but writing only to `FD1`.
Program1Name = "example_program1"
// Program2Name is the name of the second example program.
// It allows reading from `FD1` and `FD2`, but writing only to `FD2`.
Program2Name = "example_program2"
)
// Program1 returns a program that allows reading from FDs `FD1` and `FD2`,
// but writing only to FD `FD1`.
func Program1(values precompiledseccomp.Values) *seccomp.Program {
return &seccomp.Program{
RuleSets: []seccomp.RuleSet{{
Rules: seccomp.NewSyscallRules().Add(
unix.SYS_READ,
seccomp.Or{
seccomp.PerArg{seccomp.EqualTo(values[FD1])},
seccomp.PerArg{seccomp.EqualTo(values[FD2])},
},
).Add(
unix.SYS_WRITE,
seccomp.PerArg{seccomp.EqualTo(values[FD1])},
),
Action: seccomp.Allow,
}},
}
}
// Program2 returns a program that allows reading from FDs `FD1` and `FD2`,
// but writing only to FD `FD2`.
func Program2(values precompiledseccomp.Values) *seccomp.Program {
return &seccomp.Program{
RuleSets: []seccomp.RuleSet{{
Rules: seccomp.NewSyscallRules().Add(
unix.SYS_READ,
seccomp.Or{
seccomp.PerArg{seccomp.EqualTo(values[FD1])},
seccomp.PerArg{seccomp.EqualTo(values[FD2])},
},
).Add(
unix.SYS_WRITE,
seccomp.PerArg{seccomp.EqualTo(values[FD2])},
),
Action: seccomp.Allow,
}},
}
}
// PrecompiledPrograms defines the seccomp-bpf programs to precompile.
// This function is called by the generated `go_binary` rule.
func PrecompiledPrograms() ([]precompiledseccomp.Program, error) {
vars := []string{FD1, FD2}
example1, err := precompiledseccomp.Precompile(Program1Name, vars, Program1)
if err != nil {
return nil, err
}
example2, err := precompiledseccomp.Precompile(Program2Name, vars, Program2)
if err != nil {
return nil, err
}
return []precompiledseccomp.Program{example1, example2}, nil
}