mirror of
https://github.com/containers/podman.git
synced 2025-09-25 15:55:32 +08:00
support multi-image (docker) archives
Support loading and saving tarballs with more than one image. Add a new `/libpod/images/export` endpoint to the rest API to allow for exporting/saving multiple images into an archive. Note that a non-release version of containers/image is vendored. A release version must be vendored before cutting a new Podman release. We force the containers/image version via a replace in the go.mod file; this way go won't try to match the versions. Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
202
vendor/github.com/containers/common/pkg/seccomp/conversion.go
generated
vendored
202
vendor/github.com/containers/common/pkg/seccomp/conversion.go
generated
vendored
@ -1,25 +1,92 @@
|
||||
// NOTE: this package has originally been copied from
|
||||
// github.com/opencontainers/runc and modified to work for other use cases
|
||||
|
||||
package seccomp
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
var goArchToSeccompArchMap = map[string]Arch{
|
||||
"386": ArchX86,
|
||||
"amd64": ArchX86_64,
|
||||
"amd64p32": ArchX32,
|
||||
"arm": ArchARM,
|
||||
"arm64": ArchAARCH64,
|
||||
"mips": ArchMIPS,
|
||||
"mips64": ArchMIPS64,
|
||||
"mips64le": ArchMIPSEL64,
|
||||
"mips64p32": ArchMIPS64N32,
|
||||
"mips64p32le": ArchMIPSEL64N32,
|
||||
"mipsle": ArchMIPSEL,
|
||||
"ppc": ArchPPC,
|
||||
"ppc64": ArchPPC64,
|
||||
"ppc64le": ArchPPC64LE,
|
||||
"s390": ArchS390,
|
||||
"s390x": ArchS390X,
|
||||
}
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
goArchToSeccompArchMap = map[string]Arch{
|
||||
"386": ArchX86,
|
||||
"amd64": ArchX86_64,
|
||||
"amd64p32": ArchX32,
|
||||
"arm": ArchARM,
|
||||
"arm64": ArchAARCH64,
|
||||
"mips": ArchMIPS,
|
||||
"mips64": ArchMIPS64,
|
||||
"mips64le": ArchMIPSEL64,
|
||||
"mips64p32": ArchMIPS64N32,
|
||||
"mips64p32le": ArchMIPSEL64N32,
|
||||
"mipsle": ArchMIPSEL,
|
||||
"ppc": ArchPPC,
|
||||
"ppc64": ArchPPC64,
|
||||
"ppc64le": ArchPPC64LE,
|
||||
"s390": ArchS390,
|
||||
"s390x": ArchS390X,
|
||||
}
|
||||
specArchToLibseccompArchMap = map[specs.Arch]string{
|
||||
specs.ArchX86: "x86",
|
||||
specs.ArchX86_64: "amd64",
|
||||
specs.ArchX32: "x32",
|
||||
specs.ArchARM: "arm",
|
||||
specs.ArchAARCH64: "arm64",
|
||||
specs.ArchMIPS: "mips",
|
||||
specs.ArchMIPS64: "mips64",
|
||||
specs.ArchMIPS64N32: "mips64n32",
|
||||
specs.ArchMIPSEL: "mipsel",
|
||||
specs.ArchMIPSEL64: "mipsel64",
|
||||
specs.ArchMIPSEL64N32: "mipsel64n32",
|
||||
specs.ArchPPC: "ppc",
|
||||
specs.ArchPPC64: "ppc64",
|
||||
specs.ArchPPC64LE: "ppc64le",
|
||||
specs.ArchS390: "s390",
|
||||
specs.ArchS390X: "s390x",
|
||||
}
|
||||
specArchToSeccompArchMap = map[specs.Arch]Arch{
|
||||
specs.ArchX86: ArchX86,
|
||||
specs.ArchX86_64: ArchX86_64,
|
||||
specs.ArchX32: ArchX32,
|
||||
specs.ArchARM: ArchARM,
|
||||
specs.ArchAARCH64: ArchAARCH64,
|
||||
specs.ArchMIPS: ArchMIPS,
|
||||
specs.ArchMIPS64: ArchMIPS64,
|
||||
specs.ArchMIPS64N32: ArchMIPS64N32,
|
||||
specs.ArchMIPSEL: ArchMIPSEL,
|
||||
specs.ArchMIPSEL64: ArchMIPSEL64,
|
||||
specs.ArchMIPSEL64N32: ArchMIPSEL64N32,
|
||||
specs.ArchPPC: ArchPPC,
|
||||
specs.ArchPPC64: ArchPPC64,
|
||||
specs.ArchPPC64LE: ArchPPC64LE,
|
||||
specs.ArchS390: ArchS390,
|
||||
specs.ArchS390X: ArchS390X,
|
||||
}
|
||||
specActionToSeccompActionMap = map[specs.LinuxSeccompAction]Action{
|
||||
specs.ActKill: ActKill,
|
||||
// TODO: wait for this PR to get merged:
|
||||
// https://github.com/opencontainers/runtime-spec/pull/1064
|
||||
// specs.ActKillProcess ActKillProcess,
|
||||
// specs.ActKillThread ActKillThread,
|
||||
specs.ActErrno: ActErrno,
|
||||
specs.ActTrap: ActTrap,
|
||||
specs.ActAllow: ActAllow,
|
||||
specs.ActTrace: ActTrace,
|
||||
specs.ActLog: ActLog,
|
||||
}
|
||||
specOperatorToSeccompOperatorMap = map[specs.LinuxSeccompOperator]Operator{
|
||||
specs.OpNotEqual: OpNotEqual,
|
||||
specs.OpLessThan: OpLessThan,
|
||||
specs.OpLessEqual: OpLessEqual,
|
||||
specs.OpEqualTo: OpEqualTo,
|
||||
specs.OpGreaterEqual: OpGreaterEqual,
|
||||
specs.OpGreaterThan: OpGreaterThan,
|
||||
specs.OpMaskedEqual: OpMaskedEqual,
|
||||
}
|
||||
)
|
||||
|
||||
// GoArchToSeccompArch converts a runtime.GOARCH to a seccomp `Arch`. The
|
||||
// function returns an error if the architecture conversion is not supported.
|
||||
@ -30,3 +97,100 @@ func GoArchToSeccompArch(goArch string) (Arch, error) {
|
||||
}
|
||||
return arch, nil
|
||||
}
|
||||
|
||||
// specToSeccomp converts a `LinuxSeccomp` spec into a `Seccomp` struct.
|
||||
func specToSeccomp(spec *specs.LinuxSeccomp) (*Seccomp, error) {
|
||||
res := &Seccomp{
|
||||
Syscalls: []*Syscall{},
|
||||
}
|
||||
|
||||
for _, arch := range spec.Architectures {
|
||||
newArch, err := specArchToSeccompArch(arch)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "convert spec arch")
|
||||
}
|
||||
res.Architectures = append(res.Architectures, newArch)
|
||||
}
|
||||
|
||||
// Convert default action
|
||||
newDefaultAction, err := specActionToSeccompAction(spec.DefaultAction)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "convert default action")
|
||||
}
|
||||
res.DefaultAction = newDefaultAction
|
||||
|
||||
// Loop through all syscall blocks and convert them to the internal format
|
||||
for _, call := range spec.Syscalls {
|
||||
newAction, err := specActionToSeccompAction(call.Action)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "convert action")
|
||||
}
|
||||
|
||||
for _, name := range call.Names {
|
||||
newCall := Syscall{
|
||||
Name: name,
|
||||
Action: newAction,
|
||||
ErrnoRet: call.ErrnoRet,
|
||||
Args: []*Arg{},
|
||||
}
|
||||
|
||||
// Loop through all the arguments of the syscall and convert them
|
||||
for _, arg := range call.Args {
|
||||
newOp, err := specOperatorToSeccompOperator(arg.Op)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "convert operator")
|
||||
}
|
||||
|
||||
newArg := Arg{
|
||||
Index: arg.Index,
|
||||
Value: arg.Value,
|
||||
ValueTwo: arg.ValueTwo,
|
||||
Op: newOp,
|
||||
}
|
||||
|
||||
newCall.Args = append(newCall.Args, &newArg)
|
||||
}
|
||||
res.Syscalls = append(res.Syscalls, &newCall)
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// specArchToLibseccompArch converts a spec arch into a libseccomp one.
|
||||
func specArchToLibseccompArch(arch specs.Arch) (string, error) {
|
||||
if res, ok := specArchToLibseccompArchMap[arch]; ok {
|
||||
return res, nil
|
||||
}
|
||||
return "", errors.Errorf(
|
||||
"architecture %q is not valid for libseccomp", arch,
|
||||
)
|
||||
}
|
||||
|
||||
// specArchToSeccompArch converts a spec arch into an internal one.
|
||||
func specArchToSeccompArch(arch specs.Arch) (Arch, error) {
|
||||
if res, ok := specArchToSeccompArchMap[arch]; ok {
|
||||
return res, nil
|
||||
}
|
||||
return "", errors.Errorf("architecture %q is not valid", arch)
|
||||
}
|
||||
|
||||
// specActionToSeccompAction converts a spec action into a seccomp one.
|
||||
func specActionToSeccompAction(action specs.LinuxSeccompAction) (Action, error) {
|
||||
if res, ok := specActionToSeccompActionMap[action]; ok {
|
||||
return res, nil
|
||||
}
|
||||
return "", errors.Errorf(
|
||||
"spec action %q is not valid internal action", action,
|
||||
)
|
||||
}
|
||||
|
||||
// specOperatorToSeccompOperator converts a spec operator into a seccomp one.
|
||||
func specOperatorToSeccompOperator(operator specs.LinuxSeccompOperator) (Operator, error) {
|
||||
if op, ok := specOperatorToSeccompOperatorMap[operator]; ok {
|
||||
return op, nil
|
||||
}
|
||||
return "", errors.Errorf(
|
||||
"spec operator %q is not a valid internal operator", operator,
|
||||
)
|
||||
}
|
||||
|
237
vendor/github.com/containers/common/pkg/seccomp/filter.go
generated
vendored
Normal file
237
vendor/github.com/containers/common/pkg/seccomp/filter.go
generated
vendored
Normal file
@ -0,0 +1,237 @@
|
||||
// +build seccomp
|
||||
|
||||
// NOTE: this package has originally been copied from
|
||||
// github.com/opencontainers/runc and modified to work for other use cases
|
||||
|
||||
package seccomp
|
||||
|
||||
import (
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
libseccomp "github.com/seccomp/libseccomp-golang"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// NOTE: this package has originally been copied from
|
||||
// github.com/opencontainers/runc and modified to work for other use cases
|
||||
|
||||
var (
|
||||
// ErrSpecNil is a possible return error from BuildFilter() and occurs if
|
||||
// the provided spec is nil.
|
||||
ErrSpecNil = errors.New("spec is nil")
|
||||
|
||||
// ErrSpecEmpty is a possible return error from BuildFilter() and occurs if
|
||||
// the provided spec has neither a DefaultAction nor any syscalls.
|
||||
ErrSpecEmpty = errors.New("spec contains neither a default action nor any syscalls")
|
||||
)
|
||||
|
||||
// BuildFilter does a basic validation for the provided seccomp profile
|
||||
// string and returns a filter for it.
|
||||
func BuildFilter(spec *specs.LinuxSeccomp) (*libseccomp.ScmpFilter, error) {
|
||||
// Sanity checking to allow consumers to act accordingly
|
||||
if spec == nil {
|
||||
return nil, ErrSpecNil
|
||||
}
|
||||
if spec.DefaultAction == "" && len(spec.Syscalls) == 0 {
|
||||
return nil, ErrSpecEmpty
|
||||
}
|
||||
|
||||
profile, err := specToSeccomp(spec)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "convert spec to seccomp profile")
|
||||
}
|
||||
|
||||
defaultAction, err := toAction(profile.DefaultAction, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "convert default action %s", profile.DefaultAction)
|
||||
}
|
||||
|
||||
filter, err := libseccomp.NewFilter(defaultAction)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "create filter for default action %s", defaultAction)
|
||||
}
|
||||
|
||||
// Add extra architectures
|
||||
for _, arch := range spec.Architectures {
|
||||
libseccompArch, err := specArchToLibseccompArch(arch)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "convert spec arch")
|
||||
}
|
||||
|
||||
scmpArch, err := libseccomp.GetArchFromString(libseccompArch)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "validate Seccomp architecture %s", arch)
|
||||
}
|
||||
|
||||
if err := filter.AddArch(scmpArch); err != nil {
|
||||
return nil, errors.Wrap(err, "add architecture to seccomp filter")
|
||||
}
|
||||
}
|
||||
|
||||
// Unset no new privs bit
|
||||
if err := filter.SetNoNewPrivsBit(false); err != nil {
|
||||
return nil, errors.Wrap(err, "set no new privileges flag")
|
||||
}
|
||||
|
||||
// Add a rule for each syscall
|
||||
for _, call := range profile.Syscalls {
|
||||
if call == nil {
|
||||
return nil, errors.New("encountered nil syscall while initializing seccomp")
|
||||
}
|
||||
|
||||
if err = matchSyscall(filter, call); err != nil {
|
||||
return nil, errors.Wrap(err, "filter matches syscall")
|
||||
}
|
||||
}
|
||||
|
||||
return filter, nil
|
||||
}
|
||||
|
||||
func matchSyscall(filter *libseccomp.ScmpFilter, call *Syscall) error {
|
||||
if call == nil || filter == nil {
|
||||
return errors.New("cannot use nil as syscall to block")
|
||||
}
|
||||
|
||||
if call.Name == "" {
|
||||
return errors.New("empty string is not a valid syscall")
|
||||
}
|
||||
|
||||
// If we can't resolve the syscall, assume it's not supported on this kernel
|
||||
// Ignore it, don't error out
|
||||
callNum, err := libseccomp.GetSyscallFromName(call.Name)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert the call's action to the libseccomp equivalent
|
||||
callAct, err := toAction(call.Action, call.ErrnoRet)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "convert action %s", call.Action)
|
||||
}
|
||||
|
||||
// Unconditional match - just add the rule
|
||||
if len(call.Args) == 0 {
|
||||
if err = filter.AddRule(callNum, callAct); err != nil {
|
||||
return errors.Wrapf(err, "add seccomp filter rule for syscall %s", call.Name)
|
||||
}
|
||||
} else {
|
||||
// Linux system calls can have at most 6 arguments
|
||||
const syscallMaxArguments int = 6
|
||||
|
||||
// If two or more arguments have the same condition,
|
||||
// Revert to old behavior, adding each condition as a separate rule
|
||||
argCounts := make([]uint, syscallMaxArguments)
|
||||
conditions := []libseccomp.ScmpCondition{}
|
||||
|
||||
for _, cond := range call.Args {
|
||||
newCond, err := toCondition(cond)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create seccomp syscall condition for syscall %s", call.Name)
|
||||
}
|
||||
|
||||
argCounts[cond.Index] += 1
|
||||
|
||||
conditions = append(conditions, newCond)
|
||||
}
|
||||
|
||||
hasMultipleArgs := false
|
||||
for _, count := range argCounts {
|
||||
if count > 1 {
|
||||
hasMultipleArgs = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if hasMultipleArgs {
|
||||
// Revert to old behavior
|
||||
// Add each condition attached to a separate rule
|
||||
for _, cond := range conditions {
|
||||
condArr := []libseccomp.ScmpCondition{cond}
|
||||
|
||||
if err = filter.AddRuleConditional(callNum, callAct, condArr); err != nil {
|
||||
return errors.Wrapf(err, "add seccomp rule for syscall %s", call.Name)
|
||||
}
|
||||
}
|
||||
} else if err = filter.AddRuleConditional(callNum, callAct, conditions); err != nil {
|
||||
// No conditions share same argument
|
||||
// Use new, proper behavior
|
||||
return errors.Wrapf(err, "add seccomp rule for syscall %s", call.Name)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// toAction converts an internal `Action` type to a `libseccomp.ScmpAction`
|
||||
// type.
|
||||
func toAction(act Action, errnoRet *uint) (libseccomp.ScmpAction, error) {
|
||||
switch act {
|
||||
case ActKill:
|
||||
return libseccomp.ActKill, nil
|
||||
case ActKillProcess:
|
||||
return libseccomp.ActKillProcess, nil
|
||||
case ActErrno:
|
||||
if errnoRet != nil {
|
||||
return libseccomp.ActErrno.SetReturnCode(int16(*errnoRet)), nil
|
||||
}
|
||||
return libseccomp.ActErrno.SetReturnCode(int16(unix.EPERM)), nil
|
||||
case ActTrap:
|
||||
return libseccomp.ActTrap, nil
|
||||
case ActAllow:
|
||||
return libseccomp.ActAllow, nil
|
||||
case ActTrace:
|
||||
if errnoRet != nil {
|
||||
return libseccomp.ActTrace.SetReturnCode(int16(*errnoRet)), nil
|
||||
}
|
||||
return libseccomp.ActTrace.SetReturnCode(int16(unix.EPERM)), nil
|
||||
case ActLog:
|
||||
return libseccomp.ActLog, nil
|
||||
default:
|
||||
return libseccomp.ActInvalid, errors.Errorf("invalid action %s", act)
|
||||
}
|
||||
}
|
||||
|
||||
// toCondition converts an internal `Arg` type to a `libseccomp.ScmpCondition`
|
||||
// type.
|
||||
func toCondition(arg *Arg) (cond libseccomp.ScmpCondition, err error) {
|
||||
if arg == nil {
|
||||
return cond, errors.New("cannot convert nil to syscall condition")
|
||||
}
|
||||
|
||||
op, err := toCompareOp(arg.Op)
|
||||
if err != nil {
|
||||
return cond, errors.Wrap(err, "convert compare operator")
|
||||
}
|
||||
|
||||
condition, err := libseccomp.MakeCondition(
|
||||
arg.Index, op, arg.Value, arg.ValueTwo,
|
||||
)
|
||||
if err != nil {
|
||||
return cond, errors.Wrap(err, "make condition")
|
||||
}
|
||||
|
||||
return condition, nil
|
||||
}
|
||||
|
||||
// toCompareOp converts an internal `Operator` type to a
|
||||
// `libseccomp.ScmpCompareOp`.
|
||||
func toCompareOp(op Operator) (libseccomp.ScmpCompareOp, error) {
|
||||
switch op {
|
||||
case OpEqualTo:
|
||||
return libseccomp.CompareEqual, nil
|
||||
case OpNotEqual:
|
||||
return libseccomp.CompareNotEqual, nil
|
||||
case OpGreaterThan:
|
||||
return libseccomp.CompareGreater, nil
|
||||
case OpGreaterEqual:
|
||||
return libseccomp.CompareGreaterEqual, nil
|
||||
case OpLessThan:
|
||||
return libseccomp.CompareLess, nil
|
||||
case OpLessEqual:
|
||||
return libseccomp.CompareLessOrEqual, nil
|
||||
case OpMaskedEqual:
|
||||
return libseccomp.CompareMaskedEqual, nil
|
||||
default:
|
||||
return libseccomp.CompareInvalid, errors.Errorf("invalid operator %s", op)
|
||||
}
|
||||
}
|
4
vendor/github.com/containers/common/pkg/seccomp/seccomp_linux.go
generated
vendored
4
vendor/github.com/containers/common/pkg/seccomp/seccomp_linux.go
generated
vendored
@ -122,7 +122,7 @@ Loop:
|
||||
}
|
||||
if len(call.Excludes.Caps) > 0 {
|
||||
for _, c := range call.Excludes.Caps {
|
||||
if inSlice(rs.Process.Capabilities.Bounding, c) {
|
||||
if rs != nil && rs.Process != nil && rs.Process.Capabilities != nil && inSlice(rs.Process.Capabilities.Bounding, c) {
|
||||
continue Loop
|
||||
}
|
||||
}
|
||||
@ -134,7 +134,7 @@ Loop:
|
||||
}
|
||||
if len(call.Includes.Caps) > 0 {
|
||||
for _, c := range call.Includes.Caps {
|
||||
if !inSlice(rs.Process.Capabilities.Bounding, c) {
|
||||
if rs != nil && rs.Process != nil && rs.Process.Capabilities != nil && !inSlice(rs.Process.Capabilities.Bounding, c) {
|
||||
continue Loop
|
||||
}
|
||||
}
|
||||
|
29
vendor/github.com/containers/common/pkg/seccomp/validate.go
generated
vendored
Normal file
29
vendor/github.com/containers/common/pkg/seccomp/validate.go
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
// +build seccomp
|
||||
|
||||
package seccomp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ValidateProfile does a basic validation for the provided seccomp profile
|
||||
// string.
|
||||
func ValidateProfile(content string) error {
|
||||
profile := &Seccomp{}
|
||||
if err := json.Unmarshal([]byte(content), &profile); err != nil {
|
||||
return errors.Wrap(err, "decoding seccomp profile")
|
||||
}
|
||||
|
||||
spec, err := setupSeccomp(profile, nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "create seccomp spec")
|
||||
}
|
||||
|
||||
if _, err := BuildFilter(spec); err != nil {
|
||||
return errors.Wrap(err, "build seccomp filter")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
2
vendor/github.com/containers/common/version/version.go
generated
vendored
2
vendor/github.com/containers/common/version/version.go
generated
vendored
@ -1,4 +1,4 @@
|
||||
package version
|
||||
|
||||
// Version is the version of the build.
|
||||
const Version = "0.20.4-dev"
|
||||
const Version = "0.21.0"
|
||||
|
Reference in New Issue
Block a user