Merge pull request #12255 from vrothberg/fix-11970

podman load: support downloading files
This commit is contained in:
OpenShift Merge Robot
2021-11-10 18:27:39 +01:00
committed by GitHub
18 changed files with 276 additions and 78 deletions

View File

@ -9,6 +9,7 @@ import (
"strings" "strings"
"github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/completion"
"github.com/containers/common/pkg/download"
"github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/registry"
"github.com/containers/podman/v3/cmd/podman/validate" "github.com/containers/podman/v3/cmd/podman/validate"
"github.com/containers/podman/v3/pkg/domain/entities" "github.com/containers/podman/v3/pkg/domain/entities"
@ -69,6 +70,20 @@ func loadFlags(cmd *cobra.Command) {
func load(cmd *cobra.Command, args []string) error { func load(cmd *cobra.Command, args []string) error {
if len(loadOpts.Input) > 0 { if len(loadOpts.Input) > 0 {
// Download the input file if needed.
if strings.HasPrefix(loadOpts.Input, "https://") || strings.HasPrefix(loadOpts.Input, "http://") {
tmpdir, err := util.DefaultContainerConfig().ImageCopyTmpDir()
if err != nil {
return err
}
tmpfile, err := download.FromURL(tmpdir, loadOpts.Input)
if err != nil {
return err
}
defer os.Remove(tmpfile)
loadOpts.Input = tmpfile
}
if _, err := os.Stat(loadOpts.Input); err != nil { if _, err := os.Stat(loadOpts.Input); err != nil {
return err return err
} }

View File

@ -28,7 +28,7 @@ Note: `:` is a restricted character and cannot be part of the file name.
#### **--input**, **-i**=*input* #### **--input**, **-i**=*input*
Read from archive file, default is STDIN. Load the specified input file instead of from stdin. The file can be on the local file system or on a server (e.g., https://server.com/archive.tar)
The remote client requires the use of this option. The remote client requires the use of this option.
@ -49,7 +49,7 @@ $ podman load --quiet -i fedora.tar
``` ```
``` ```
$ podman load -q -i fedora.tar $ podman load -q -i https://server.com/archive.tar
``` ```
``` ```

2
go.mod
View File

@ -12,7 +12,7 @@ require (
github.com/containernetworking/cni v1.0.1 github.com/containernetworking/cni v1.0.1
github.com/containernetworking/plugins v1.0.1 github.com/containernetworking/plugins v1.0.1
github.com/containers/buildah v1.23.1 github.com/containers/buildah v1.23.1
github.com/containers/common v0.46.1-0.20211109131927-c342e496bf76 github.com/containers/common v0.46.1-0.20211110143743-73e7b462c358
github.com/containers/conmon v2.0.20+incompatible github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.16.1 github.com/containers/image/v5 v5.16.1
github.com/containers/ocicrypt v1.1.2 github.com/containers/ocicrypt v1.1.2

4
go.sum
View File

@ -258,8 +258,8 @@ github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNB
github.com/containers/buildah v1.23.1 h1:Tpc9DsRuU+0Oofewpxb6OJVNQjCu7yloN/obUqzfDTY= github.com/containers/buildah v1.23.1 h1:Tpc9DsRuU+0Oofewpxb6OJVNQjCu7yloN/obUqzfDTY=
github.com/containers/buildah v1.23.1/go.mod h1:4WnrN0yrA7ab0ppgunixu2WM1rlD2rG8QLJAKbEkZlQ= github.com/containers/buildah v1.23.1/go.mod h1:4WnrN0yrA7ab0ppgunixu2WM1rlD2rG8QLJAKbEkZlQ=
github.com/containers/common v0.44.2/go.mod h1:7sdP4vmI5Bm6FPFxb3lvAh1Iktb6tiO1MzjUzhxdoGo= github.com/containers/common v0.44.2/go.mod h1:7sdP4vmI5Bm6FPFxb3lvAh1Iktb6tiO1MzjUzhxdoGo=
github.com/containers/common v0.46.1-0.20211109131927-c342e496bf76 h1:5aDACNS6Rz+6f6rpgbv5tVG/zv1rFoPX1CYAy4Vv6ZI= github.com/containers/common v0.46.1-0.20211110143743-73e7b462c358 h1:dK2AgGBdWspdQNw28Wc4peY25QeyYV4H9ViQaFaQ9XQ=
github.com/containers/common v0.46.1-0.20211109131927-c342e496bf76/go.mod h1:bu8gizEkgAz6gXHvUw2cMtI5ErxB+fn/hv49RWk5N1A= github.com/containers/common v0.46.1-0.20211110143743-73e7b462c358/go.mod h1:bu8gizEkgAz6gXHvUw2cMtI5ErxB+fn/hv49RWk5N1A=
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.16.0/go.mod h1:XgTpfAPLRGOd1XYyCU5cISFr777bLmOerCSpt/v7+Q4= github.com/containers/image/v5 v5.16.0/go.mod h1:XgTpfAPLRGOd1XYyCU5cISFr777bLmOerCSpt/v7+Q4=

View File

@ -126,6 +126,26 @@ verify_iid_and_name() {
verify_iid_and_name $img_name verify_iid_and_name $img_name
} }
@test "podman load - from URL" {
get_iid_and_name
run_podman save $img_name -o $archive
run_podman rmi $iid
HOST_PORT=$(random_free_port)
SERVER=http://127.0.0.1:$HOST_PORT
# Bind-mount the archive to a container running httpd
run_podman run -d --name myweb -p "$HOST_PORT:80" \
-v $archive:/var/www/image.tar:Z \
-w /var/www \
$IMAGE /bin/busybox-extras httpd -f -p 80
run_podman load -i $SERVER/image.tar
verify_iid_and_name $img_name
run_podman rm -f -t0 myweb
}
@test "podman load - redirect corrupt payload" { @test "podman load - redirect corrupt payload" {
run_podman 125 load <<< "Danger, Will Robinson!! This is a corrupt tarball!" run_podman 125 load <<< "Danger, Will Robinson!! This is a corrupt tarball!"
is "$output" \ is "$output" \

View File

@ -1,46 +0,0 @@
package libimage
import (
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"github.com/pkg/errors"
)
// tmpdir returns a path to a temporary directory.
func tmpdir() string {
tmpdir := os.Getenv("TMPDIR")
if tmpdir == "" {
tmpdir = "/var/tmp"
}
return tmpdir
}
// downloadFromURL downloads an image in the format "https:/example.com/myimage.tar"
// and temporarily saves in it $TMPDIR/importxyz, which is deleted after the image is imported
func (r *Runtime) downloadFromURL(source string) (string, error) {
fmt.Printf("Downloading from %q\n", source)
outFile, err := ioutil.TempFile(r.systemContext.BigFilesTemporaryDir, "import")
if err != nil {
return "", errors.Wrap(err, "error creating file")
}
defer outFile.Close()
response, err := http.Get(source) // nolint:noctx
if err != nil {
return "", errors.Wrapf(err, "error downloading %q", source)
}
defer response.Body.Close()
_, err = io.Copy(outFile, response.Body)
if err != nil {
return "", errors.Wrapf(err, "error saving %s to %s", source, outFile.Name())
}
return outFile.Name(), nil
}

View File

@ -2,9 +2,11 @@ package libimage
import ( import (
"context" "context"
"fmt"
"net/url" "net/url"
"os" "os"
"github.com/containers/common/pkg/download"
storageTransport "github.com/containers/image/v5/storage" storageTransport "github.com/containers/image/v5/storage"
tarballTransport "github.com/containers/image/v5/tarball" tarballTransport "github.com/containers/image/v5/tarball"
v1 "github.com/opencontainers/image-spec/specs-go/v1" v1 "github.com/opencontainers/image-spec/specs-go/v1"
@ -61,7 +63,8 @@ func (r *Runtime) Import(ctx context.Context, path string, options *ImportOption
u, err := url.ParseRequestURI(path) u, err := url.ParseRequestURI(path)
if err == nil && u.Scheme != "" { if err == nil && u.Scheme != "" {
// If source is a URL, download the file. // If source is a URL, download the file.
file, err := r.downloadFromURL(path) fmt.Printf("Downloading from %q\n", path)
file, err := download.FromURL(r.systemContext.BigFilesTemporaryDir, path)
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@ -21,6 +21,16 @@ import (
// Faster than the standard library, see https://github.com/json-iterator/go. // Faster than the standard library, see https://github.com/json-iterator/go.
var json = jsoniter.ConfigCompatibleWithStandardLibrary var json = jsoniter.ConfigCompatibleWithStandardLibrary
// tmpdir returns a path to a temporary directory.
func tmpdir() string {
tmpdir := os.Getenv("TMPDIR")
if tmpdir == "" {
tmpdir = "/var/tmp"
}
return tmpdir
}
// RuntimeOptions allow for creating a customized Runtime. // RuntimeOptions allow for creating a customized Runtime.
type RuntimeOptions struct { type RuntimeOptions struct {
// The base system context of the runtime which will be used throughout // The base system context of the runtime which will be used throughout

View File

@ -461,6 +461,10 @@ type SetOptions struct {
// NetworkConfig represents the "network" TOML config table // NetworkConfig represents the "network" TOML config table
type NetworkConfig struct { type NetworkConfig struct {
// NetworkBackend determines what backend should be used for Podman's
// networking.
NetworkBackend string `toml:"network_backend,omitempty"`
// CNIPluginDirs is where CNI plugin binaries are stored. // CNIPluginDirs is where CNI plugin binaries are stored.
CNIPluginDirs []string `toml:"cni_plugin_dirs,omitempty"` CNIPluginDirs []string `toml:"cni_plugin_dirs,omitempty"`

View File

@ -260,6 +260,10 @@ default_sysctls = [
[network] [network]
# Network backend to use. Default "CNI".
#
#network_backend = "cni"
# Path to directory where CNI plugin binaries are located. # Path to directory where CNI plugin binaries are located.
# #
#cni_plugin_dirs = [ #cni_plugin_dirs = [

View File

@ -201,6 +201,7 @@ func DefaultConfig() (*Config, error) {
UserNSSize: DefaultUserNSSize, UserNSSize: DefaultUserNSSize,
}, },
Network: NetworkConfig{ Network: NetworkConfig{
NetworkBackend: "cni",
DefaultNetwork: "podman", DefaultNetwork: "podman",
DefaultSubnet: DefaultSubnet, DefaultSubnet: DefaultSubnet,
NetworkConfigDir: cniConfig, NetworkConfigDir: cniConfig,

View File

@ -0,0 +1,31 @@
package download
import (
"fmt"
"io"
"io/ioutil"
"net/http"
)
// FromURL downloads the specified source to a file in tmpdir (OS defaults if
// empty).
func FromURL(tmpdir, source string) (string, error) {
tmp, err := ioutil.TempFile(tmpdir, "")
if err != nil {
return "", fmt.Errorf("creating temporary download file: %w", err)
}
defer tmp.Close()
response, err := http.Get(source) // nolint:noctx
if err != nil {
return "", fmt.Errorf("downloading %s: %w", source, err)
}
defer response.Body.Close()
_, err = io.Copy(tmp, response.Body)
if err != nil {
return "", fmt.Errorf("copying %s to %s: %w", source, tmp.Name(), err)
}
return tmp.Name(), nil
}

View File

@ -80,6 +80,7 @@ func DefaultProfile() *Seccomp {
"vmsplice", "vmsplice",
}, },
Action: ActErrno, Action: ActErrno,
Errno: "EPERM",
ErrnoRet: &eperm, ErrnoRet: &eperm,
Args: []*Arg{}, Args: []*Arg{},
}, },
@ -574,6 +575,7 @@ func DefaultProfile() *Seccomp {
"open_by_handle_at", "open_by_handle_at",
}, },
Action: ActErrno, Action: ActErrno,
Errno: "EPERM",
ErrnoRet: &eperm, ErrnoRet: &eperm,
Args: []*Arg{}, Args: []*Arg{},
Excludes: Filter{ Excludes: Filter{
@ -609,6 +611,7 @@ func DefaultProfile() *Seccomp {
"setns", "setns",
}, },
Action: ActErrno, Action: ActErrno,
Errno: "EPERM",
ErrnoRet: &eperm, ErrnoRet: &eperm,
Args: []*Arg{}, Args: []*Arg{},
Excludes: Filter{ Excludes: Filter{
@ -630,6 +633,7 @@ func DefaultProfile() *Seccomp {
"chroot", "chroot",
}, },
Action: ActErrno, Action: ActErrno,
Errno: "EPERM",
ErrnoRet: &eperm, ErrnoRet: &eperm,
Args: []*Arg{}, Args: []*Arg{},
Excludes: Filter{ Excludes: Filter{
@ -657,6 +661,7 @@ func DefaultProfile() *Seccomp {
"query_module", "query_module",
}, },
Action: ActErrno, Action: ActErrno,
Errno: "EPERM",
ErrnoRet: &eperm, ErrnoRet: &eperm,
Args: []*Arg{}, Args: []*Arg{},
Excludes: Filter{ Excludes: Filter{
@ -678,6 +683,7 @@ func DefaultProfile() *Seccomp {
"acct", "acct",
}, },
Action: ActErrno, Action: ActErrno,
Errno: "EPERM",
ErrnoRet: &eperm, ErrnoRet: &eperm,
Args: []*Arg{}, Args: []*Arg{},
Excludes: Filter{ Excludes: Filter{
@ -707,6 +713,7 @@ func DefaultProfile() *Seccomp {
"ptrace", "ptrace",
}, },
Action: ActErrno, Action: ActErrno,
Errno: "EPERM",
ErrnoRet: &eperm, ErrnoRet: &eperm,
Args: []*Arg{}, Args: []*Arg{},
Excludes: Filter{ Excludes: Filter{
@ -730,6 +737,7 @@ func DefaultProfile() *Seccomp {
"ioperm", "ioperm",
}, },
Action: ActErrno, Action: ActErrno,
Errno: "EPERM",
ErrnoRet: &eperm, ErrnoRet: &eperm,
Args: []*Arg{}, Args: []*Arg{},
Excludes: Filter{ Excludes: Filter{
@ -757,6 +765,7 @@ func DefaultProfile() *Seccomp {
"clock_settime64", "clock_settime64",
}, },
Action: ActErrno, Action: ActErrno,
Errno: "EPERM",
ErrnoRet: &eperm, ErrnoRet: &eperm,
Args: []*Arg{}, Args: []*Arg{},
Excludes: Filter{ Excludes: Filter{
@ -778,6 +787,7 @@ func DefaultProfile() *Seccomp {
"vhangup", "vhangup",
}, },
Action: ActErrno, Action: ActErrno,
Errno: "EPERM",
ErrnoRet: &eperm, ErrnoRet: &eperm,
Args: []*Arg{}, Args: []*Arg{},
Excludes: Filter{ Excludes: Filter{
@ -789,6 +799,7 @@ func DefaultProfile() *Seccomp {
"socket", "socket",
}, },
Action: ActErrno, Action: ActErrno,
Errno: "EINVAL",
ErrnoRet: &einval, ErrnoRet: &einval,
Args: []*Arg{ Args: []*Arg{
{ {
@ -867,6 +878,7 @@ func DefaultProfile() *Seccomp {
return &Seccomp{ return &Seccomp{
DefaultAction: ActErrno, DefaultAction: ActErrno,
DefaultErrno: "ENOSYS",
DefaultErrnoRet: &enosys, DefaultErrnoRet: &enosys,
ArchMap: arches(), ArchMap: arches(),
Syscalls: syscalls, Syscalls: syscalls,

View File

@ -0,0 +1,91 @@
package seccomp
import (
"golang.org/x/sys/unix"
)
// Error table
var errnoArch = map[string]uint{
"EPERM": uint(unix.EPERM),
"ENOENT": uint(unix.ENOENT),
"ESRCH": uint(unix.ESRCH),
"EIO": uint(unix.EIO),
"ENXIO": uint(unix.ENXIO),
"E2BIG": uint(unix.E2BIG),
"ENOEXEC": uint(unix.ENOEXEC),
"EBADF": uint(unix.EBADF),
"ECHILD": uint(unix.ECHILD),
"EDEADLK": uint(unix.EDEADLK),
"ENOMEM": uint(unix.ENOMEM),
"EACCES": uint(unix.EACCES),
"EFAULT": uint(unix.EFAULT),
"ENOTBLK": uint(unix.ENOTBLK),
"EBUSY": uint(unix.EBUSY),
"EEXIST": uint(unix.EEXIST),
"EXDEV": uint(unix.EXDEV),
"ENODEV": uint(unix.ENODEV),
"ENOTDIR": uint(unix.ENOTDIR),
"EISDIR": uint(unix.EISDIR),
"EINVAL": uint(unix.EINVAL),
"ENFILE": uint(unix.ENFILE),
"EMFILE": uint(unix.EMFILE),
"ENOTTY": uint(unix.ENOTTY),
"ETXTBSY": uint(unix.ETXTBSY),
"EFBIG": uint(unix.EFBIG),
"ENOSPC": uint(unix.ENOSPC),
"ESPIPE": uint(unix.ESPIPE),
"EROFS": uint(unix.EROFS),
"EMLINK": uint(unix.EMLINK),
"EPIPE": uint(unix.EPIPE),
"EDOM": uint(unix.EDOM),
"ERANGE": uint(unix.ERANGE),
"EAGAIN": uint(unix.EAGAIN),
"EINPROGRESS": uint(unix.EINPROGRESS),
"EALREADY": uint(unix.EALREADY),
"ENOTSOCK": uint(unix.ENOTSOCK),
"EDESTADDRREQ": uint(unix.EDESTADDRREQ),
"EMSGSIZE": uint(unix.EMSGSIZE),
"EPROTOTYPE": uint(unix.EPROTOTYPE),
"ENOPROTOOPT": uint(unix.ENOPROTOOPT),
"EPROTONOSUPPORT": uint(unix.EPROTONOSUPPORT),
"ESOCKTNOSUPPORT": uint(unix.ESOCKTNOSUPPORT),
"EOPNOTSUPP": uint(unix.EOPNOTSUPP),
"EPFNOSUPPORT": uint(unix.EPFNOSUPPORT),
"EAFNOSUPPORT": uint(unix.EAFNOSUPPORT),
"EADDRINUSE": uint(unix.EADDRINUSE),
"EADDRNOTAVAIL": uint(unix.EADDRNOTAVAIL),
"ENETDOWN": uint(unix.ENETDOWN),
"ENETUNREACH": uint(unix.ENETUNREACH),
"ENETRESET": uint(unix.ENETRESET),
"ECONNABORTED": uint(unix.ECONNABORTED),
"ECONNRESET": uint(unix.ECONNRESET),
"ENOBUFS": uint(unix.ENOBUFS),
"EISCONN": uint(unix.EISCONN),
"ENOTCONN": uint(unix.ENOTCONN),
"ESHUTDOWN": uint(unix.ESHUTDOWN),
"ETOOMANYREFS": uint(unix.ETOOMANYREFS),
"ETIMEDOUT": uint(unix.ETIMEDOUT),
"ECONNREFUSED": uint(unix.ECONNREFUSED),
"ELOOP": uint(unix.ELOOP),
"ENAMETOOLONG": uint(unix.ENAMETOOLONG),
"EHOSTDOWN": uint(unix.EHOSTDOWN),
"EHOSTUNREACH": uint(unix.EHOSTUNREACH),
"ENOTEMPTY": uint(unix.ENOTEMPTY),
"EUSERS": uint(unix.EUSERS),
"EDQUOT": uint(unix.EDQUOT),
"ESTALE": uint(unix.ESTALE),
"EREMOTE": uint(unix.EREMOTE),
"ENOLCK": uint(unix.ENOLCK),
"ENOSYS": uint(unix.ENOSYS),
"EILSEQ": uint(unix.EILSEQ),
"ENOMEDIUM": uint(unix.ENOMEDIUM),
"EMEDIUMTYPE": uint(unix.EMEDIUMTYPE),
"EOVERFLOW": uint(unix.EOVERFLOW),
"ECANCELED": uint(unix.ECANCELED),
"EIDRM": uint(unix.EIDRM),
"ENOMSG": uint(unix.ENOMSG),
"ENOTSUP": uint(unix.ENOTSUP),
"EBADMSG": uint(unix.EBADMSG),
"ENOTRECOVERABLE": uint(unix.ENOTRECOVERABLE),
"EOWNERDEAD": uint(unix.EOWNERDEAD),
}

View File

@ -1,6 +1,7 @@
{ {
"defaultAction": "SCMP_ACT_ERRNO", "defaultAction": "SCMP_ACT_ERRNO",
"defaultErrnoRet": 38, "defaultErrnoRet": 38,
"defaultErrno": "ENOSYS",
"archMap": [ "archMap": [
{ {
"architecture": "SCMP_ARCH_X86_64", "architecture": "SCMP_ARCH_X86_64",
@ -87,7 +88,8 @@
"comment": "", "comment": "",
"includes": {}, "includes": {},
"excludes": {}, "excludes": {},
"errnoRet": 1 "errnoRet": 1,
"errno": "EPERM"
}, },
{ {
"names": [ "names": [
@ -650,7 +652,8 @@
"CAP_DAC_READ_SEARCH" "CAP_DAC_READ_SEARCH"
] ]
}, },
"errnoRet": 1 "errnoRet": 1,
"errno": "EPERM"
}, },
{ {
"names": [ "names": [
@ -693,7 +696,8 @@
"CAP_SYS_ADMIN" "CAP_SYS_ADMIN"
] ]
}, },
"errnoRet": 1 "errnoRet": 1,
"errno": "EPERM"
}, },
{ {
"names": [ "names": [
@ -722,7 +726,8 @@
"CAP_SYS_CHROOT" "CAP_SYS_CHROOT"
] ]
}, },
"errnoRet": 1 "errnoRet": 1,
"errno": "EPERM"
}, },
{ {
"names": [ "names": [
@ -757,7 +762,8 @@
"CAP_SYS_MODULE" "CAP_SYS_MODULE"
] ]
}, },
"errnoRet": 1 "errnoRet": 1,
"errno": "EPERM"
}, },
{ {
"names": [ "names": [
@ -786,7 +792,8 @@
"CAP_SYS_PACCT" "CAP_SYS_PACCT"
] ]
}, },
"errnoRet": 1 "errnoRet": 1,
"errno": "EPERM"
}, },
{ {
"names": [ "names": [
@ -823,7 +830,8 @@
"CAP_SYS_PTRACE" "CAP_SYS_PTRACE"
] ]
}, },
"errnoRet": 1 "errnoRet": 1,
"errno": "EPERM"
}, },
{ {
"names": [ "names": [
@ -854,7 +862,8 @@
"CAP_SYS_RAWIO" "CAP_SYS_RAWIO"
] ]
}, },
"errnoRet": 1 "errnoRet": 1,
"errno": "EPERM"
}, },
{ {
"names": [ "names": [
@ -889,7 +898,8 @@
"CAP_SYS_TIME" "CAP_SYS_TIME"
] ]
}, },
"errnoRet": 1 "errnoRet": 1,
"errno": "EPERM"
}, },
{ {
"names": [ "names": [
@ -918,7 +928,8 @@
"CAP_SYS_TTY_CONFIG" "CAP_SYS_TTY_CONFIG"
] ]
}, },
"errnoRet": 1 "errnoRet": 1,
"errno": "EPERM"
}, },
{ {
"names": [ "names": [
@ -946,7 +957,8 @@
"CAP_AUDIT_WRITE" "CAP_AUDIT_WRITE"
] ]
}, },
"errnoRet": 22 "errnoRet": 22,
"errno": "EINVAL"
}, },
{ {
"names": [ "names": [

View File

@ -10,6 +10,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"strconv"
"github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-spec/specs-go"
libseccomp "github.com/seccomp/libseccomp-golang" libseccomp "github.com/seccomp/libseccomp-golang"
@ -66,6 +67,37 @@ func inSlice(slice []string, s string) bool {
return false return false
} }
func getArchitectures(config *Seccomp, newConfig *specs.LinuxSeccomp) error {
if len(config.Architectures) != 0 && len(config.ArchMap) != 0 {
return errors.New("'architectures' and 'archMap' were specified in the seccomp profile, use either 'architectures' or 'archMap'")
}
// if config.Architectures == 0 then libseccomp will figure out the architecture to use
if len(config.Architectures) != 0 {
for _, a := range config.Architectures {
newConfig.Architectures = append(newConfig.Architectures, specs.Arch(a))
}
}
return nil
}
func getErrno(errno string, def *uint) (*uint, error) {
if errno == "" {
return def, nil
}
v, err := strconv.ParseUint(errno, 10, 32)
if err == nil {
v2 := uint(v)
return &v2, nil
}
v2, found := errnoArch[errno]
if !found {
return nil, fmt.Errorf("unknown errno %s", errno)
}
return &v2, nil
}
func setupSeccomp(config *Seccomp, rs *specs.Spec) (*specs.LinuxSeccomp, error) { func setupSeccomp(config *Seccomp, rs *specs.Spec) (*specs.LinuxSeccomp, error) {
if config == nil { if config == nil {
return nil, nil return nil, nil
@ -84,15 +116,8 @@ func setupSeccomp(config *Seccomp, rs *specs.Spec) (*specs.LinuxSeccomp, error)
arch = native.String() arch = native.String()
} }
if len(config.Architectures) != 0 && len(config.ArchMap) != 0 { if err := getArchitectures(config, newConfig); err != nil {
return nil, errors.New("'architectures' and 'archMap' were specified in the seccomp profile, use either 'architectures' or 'archMap'") return nil, err
}
// if config.Architectures == 0 then libseccomp will figure out the architecture to use
if len(config.Architectures) != 0 {
for _, a := range config.Architectures {
newConfig.Architectures = append(newConfig.Architectures, specs.Arch(a))
}
} }
if len(config.ArchMap) != 0 { if len(config.ArchMap) != 0 {
@ -111,7 +136,11 @@ func setupSeccomp(config *Seccomp, rs *specs.Spec) (*specs.LinuxSeccomp, error)
} }
newConfig.DefaultAction = specs.LinuxSeccompAction(config.DefaultAction) newConfig.DefaultAction = specs.LinuxSeccompAction(config.DefaultAction)
newConfig.DefaultErrnoRet = config.DefaultErrnoRet
newConfig.DefaultErrnoRet, err = getErrno(config.DefaultErrno, config.DefaultErrnoRet)
if err != nil {
return nil, err
}
Loop: Loop:
// Loop through all syscall blocks and convert them to libcontainer format after filtering them // Loop through all syscall blocks and convert them to libcontainer format after filtering them
@ -145,12 +174,17 @@ Loop:
return nil, errors.New("'name' and 'names' were specified in the seccomp profile, use either 'name' or 'names'") return nil, errors.New("'name' and 'names' were specified in the seccomp profile, use either 'name' or 'names'")
} }
errno, err := getErrno(call.Errno, call.ErrnoRet)
if err != nil {
return nil, err
}
if call.Name != "" { if call.Name != "" {
newConfig.Syscalls = append(newConfig.Syscalls, createSpecsSyscall([]string{call.Name}, call.Action, call.Args, call.ErrnoRet)) newConfig.Syscalls = append(newConfig.Syscalls, createSpecsSyscall([]string{call.Name}, call.Action, call.Args, errno))
} }
if len(call.Names) > 0 { if len(call.Names) > 0 {
newConfig.Syscalls = append(newConfig.Syscalls, createSpecsSyscall(call.Names, call.Action, call.Args, call.ErrnoRet)) newConfig.Syscalls = append(newConfig.Syscalls, createSpecsSyscall(call.Names, call.Action, call.Args, errno))
} }
} }

View File

@ -6,8 +6,12 @@ package seccomp
// Seccomp represents the config for a seccomp profile for syscall restriction. // Seccomp represents the config for a seccomp profile for syscall restriction.
type Seccomp struct { type Seccomp struct {
DefaultAction Action `json:"defaultAction"` DefaultAction Action `json:"defaultAction"`
// DefaultErrnoRet is obsolete, please use DefaultErrno
DefaultErrnoRet *uint `json:"defaultErrnoRet,omitempty"` DefaultErrnoRet *uint `json:"defaultErrnoRet,omitempty"`
DefaultErrno string `json:"defaultErrno,omitempty"`
// Architectures is kept to maintain backward compatibility with the old // Architectures is kept to maintain backward compatibility with the old
// seccomp profile. // seccomp profile.
Architectures []Arch `json:"architectures,omitempty"` Architectures []Arch `json:"architectures,omitempty"`
@ -107,5 +111,7 @@ type Syscall struct {
Comment string `json:"comment"` Comment string `json:"comment"`
Includes Filter `json:"includes"` Includes Filter `json:"includes"`
Excludes Filter `json:"excludes"` Excludes Filter `json:"excludes"`
ErrnoRet *uint `json:"errnoRet,omitempty"` // ErrnoRet is obsolete, please use Errno
ErrnoRet *uint `json:"errnoRet,omitempty"`
Errno string `json:"errno,omitempty"`
} }

3
vendor/modules.txt vendored
View File

@ -97,7 +97,7 @@ github.com/containers/buildah/pkg/rusage
github.com/containers/buildah/pkg/sshagent github.com/containers/buildah/pkg/sshagent
github.com/containers/buildah/pkg/util github.com/containers/buildah/pkg/util
github.com/containers/buildah/util github.com/containers/buildah/util
# github.com/containers/common v0.46.1-0.20211109131927-c342e496bf76 # github.com/containers/common v0.46.1-0.20211110143743-73e7b462c358
github.com/containers/common/libimage github.com/containers/common/libimage
github.com/containers/common/libimage/manifests github.com/containers/common/libimage/manifests
github.com/containers/common/pkg/apparmor github.com/containers/common/pkg/apparmor
@ -109,6 +109,7 @@ github.com/containers/common/pkg/chown
github.com/containers/common/pkg/completion github.com/containers/common/pkg/completion
github.com/containers/common/pkg/config github.com/containers/common/pkg/config
github.com/containers/common/pkg/defaultnet github.com/containers/common/pkg/defaultnet
github.com/containers/common/pkg/download
github.com/containers/common/pkg/filters github.com/containers/common/pkg/filters
github.com/containers/common/pkg/flag github.com/containers/common/pkg/flag
github.com/containers/common/pkg/manifests github.com/containers/common/pkg/manifests