mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-10 21:53:57 +08:00
Merge pull request #5141 from cyphar/remove-deprecated-apis
libct: remove deprecated APIs
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
vendor/pkg
|
||||
/runc
|
||||
/runc-*
|
||||
/contrib/cmd/memfd-bind/memfd-bind
|
||||
/tests/cmd/_bin
|
||||
man/man8
|
||||
release
|
||||
|
||||
@@ -6,6 +6,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### libcontainer API ###
|
||||
- The following deprecated Go APIs have been removed:
|
||||
- `CleanPath`, `StripRoot`, and `WithProcfd` from `libcontainer/utils`. Note
|
||||
that `WithProcfdFile` has not been removed (due to import cycle issues) but
|
||||
is instead marked as internal in its godoc comment. (#5051)
|
||||
- All of the cgroup-related types and functions from `libcontainer/configs`
|
||||
which are now maintained in `github.com/opencontainers/cgroups` (#5141):
|
||||
- `libcontainer/configs.Cgroup`
|
||||
- `libcontainer/configs.Resources`
|
||||
- `libcontainer/configs.FreezerState`
|
||||
- `libcontainer/configs.LinuxRdma`
|
||||
- `libcontainer/configs.BlockIODevice`
|
||||
- `libcontainer/configs.WeightDevice`
|
||||
- `libcontainer/configs.ThrottleDevice`
|
||||
- `libcontainer/configs.HugepageLimit`
|
||||
- `libcontainer/configs.IfPrioMap`
|
||||
- `libcontainer/configs.Undefined`
|
||||
- `libcontainer/configs.Frozen`
|
||||
- `libcontainer/configs.Thawed`
|
||||
- `libcontainer/configs.NewWeightDevice`
|
||||
- `libcontainer/configs.NewThrottleDevice`
|
||||
- `libcontainer/configs.HookList.RunHooks`. (#5141)
|
||||
- `libcontainer/configs.MPOL_*` (#5414)
|
||||
- All of the types in `libcontainer/devices` which are now maintained in
|
||||
`github.com/opencontainers/cgroups/devices/config` (#5141):
|
||||
- `libcontainer/devices.Wildcard`
|
||||
- `libcontainer/devices.WildcardDevice`
|
||||
- `libcontainer/devices.BlockDevice`
|
||||
- `libcontainer/devices.CharDevice`
|
||||
- `libcontainer/devices.FifoDevice`
|
||||
- `libcontainer/devices.Device`
|
||||
- `libcontainer/devices.Permissions`
|
||||
- `libcontainer/devices.Type`
|
||||
- `libcontainer/devices.Rule`
|
||||
|
||||
### Removed ###
|
||||
- The `memfd-bind` helper binary has been removed, as it has never been
|
||||
particularly useful and was completely obsoleted by the changes to
|
||||
`/proc/self/exe` sealing we introduced in runc [1.2.0][]. (#5141)
|
||||
|
||||
## [1.4.0] - 2025-11-27
|
||||
|
||||
> 路漫漫其修远兮,吾将上下而求索!
|
||||
|
||||
@@ -77,11 +77,7 @@ runc-bin:
|
||||
$(GO_BUILD) -o runc .
|
||||
|
||||
.PHONY: all
|
||||
all: runc memfd-bind
|
||||
|
||||
.PHONY: memfd-bind
|
||||
memfd-bind:
|
||||
$(GO_BUILD) -o contrib/cmd/$@/$@ ./contrib/cmd/$@
|
||||
all: runc
|
||||
|
||||
TESTBINDIR := tests/cmd/_bin
|
||||
$(TESTBINDIR):
|
||||
@@ -96,7 +92,6 @@ $(TESTBINS): $(TESTBINDIR)
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f runc runc-*
|
||||
rm -f contrib/cmd/memfd-bind/memfd-bind
|
||||
rm -fr $(TESTBINDIR)
|
||||
sudo rm -rf release
|
||||
rm -rf man/man8
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
## memfd-bind ##
|
||||
|
||||
> **NOTE**: Since runc 1.2.0, runc will now use a private overlayfs mount to
|
||||
> protect the runc binary (if you are on Linux 5.1 or later). This protection
|
||||
> is far more light-weight than memfd-bind, and for most users this should
|
||||
> obviate the need for `memfd-bind` entirely. Rootless containers will still
|
||||
> make a memfd copy (unless you are using `runc` itself inside a user namespace
|
||||
> -- a-la [`rootlesskit`][rootlesskit] -- and are on Linux 5.11 or later), but
|
||||
> `memfd-bind` is not particularly useful for rootless container users anyway
|
||||
> (see [Caveats](#Caveats) for more details).
|
||||
|
||||
`runc` sometimes has to make a binary copy of itself when constructing a
|
||||
container process in order to defend against certain container runtime attacks
|
||||
such as CVE-2019-5736.
|
||||
|
||||
This cloned binary only exists until the container process starts (this means
|
||||
for `runc run` and `runc exec`, it only exists for a few hundred milliseconds
|
||||
-- for `runc create` it exists until `runc start` is called). However, because
|
||||
the clone is done using a memfd (or by creating files in directories that are
|
||||
likely to be a `tmpfs`), this can lead to temporary increases in *host* memory
|
||||
usage. Unless you are running on a cgroupv1 system with the cgroupv1 memory
|
||||
controller enabled and the (deprecated) `memory.move_charge_at_immigrate`
|
||||
enabled, there is no effect on the container's memory.
|
||||
|
||||
However, for certain configurations this can still be undesirable. This daemon
|
||||
allows you to create a sealed memfd copy of the `runc` binary, which will cause
|
||||
`runc` to skip all binary copying, resulting in no additional memory usage for
|
||||
each container process (instead there is a single in-memory copy of the
|
||||
binary). It should be noted that (strictly speaking) this is slightly less
|
||||
secure if you are concerned about Dirty Cow-like 0-day kernel vulnerabilities,
|
||||
but for most users the security benefit is identical.
|
||||
|
||||
The provided `memfd-bind@.service` file can be used to get systemd to manage
|
||||
this daemon. You can supply the path like so:
|
||||
|
||||
```bash
|
||||
systemctl start memfd-bind@$(systemd-escape -p /usr/bin/runc)
|
||||
```
|
||||
|
||||
Thus, there are three ways of protecting against CVE-2019-5736, in order of how
|
||||
much memory usage they can use:
|
||||
|
||||
* `memfd-bind` only creates a single in-memory copy of the `runc` binary (about
|
||||
10MB), regardless of how many containers are running.
|
||||
|
||||
* The classic method of making a copy of the entire `runc` binary during
|
||||
container process setup takes up about 10MB per process spawned inside the
|
||||
container by runc (both pid1 and `runc exec`).
|
||||
|
||||
[rootlesskit]: https://github.com/rootless-containers/rootlesskit
|
||||
|
||||
### Caveats ###
|
||||
|
||||
There are several downsides with using `memfd-bind` on the `runc` binary:
|
||||
|
||||
* The `memfd-bind` process needs to continue to run indefinitely in order for
|
||||
the memfd reference to stay alive. If the process is forcefully killed, the
|
||||
bind-mount on top of the `runc` binary will become stale and nobody will be
|
||||
able to execute it (you can use `memfd-bind --cleanup` to clean up the stale
|
||||
mount).
|
||||
|
||||
* Only root can execute the cloned binary due to permission restrictions on
|
||||
accessing other process's files. More specifically, only users with ptrace
|
||||
privileges over the memfd-bind daemon can access the file (but in practice
|
||||
this is usually only root).
|
||||
|
||||
* When updating `runc`, the daemon needs to be stopped before the update (so
|
||||
the package manager can access the underlying file) and then restarted after
|
||||
the update.
|
||||
@@ -1,251 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2023 SUSE LLC
|
||||
* Copyright (c) 2023 Aleksa Sarai <cyphar@cyphar.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// memfd-bind is a command-line tool to construct a persistent
|
||||
// sealed-memfd-copy of a binary, to allow administrators to amortise the cost
|
||||
// of memfd cloning for runc. runc will not make its own copy of the binary if
|
||||
// it detects that the binary is already a sealed-memfd-copy.
|
||||
//
|
||||
// Usage of this tool has a lot of caveats -- see this package's README for
|
||||
// more details on what restrictions apply when using this tool.
|
||||
//
|
||||
// Deprecated: runc 1.2 and later use a different mechanism for protecting the
|
||||
// runc binary that obviates the need for this tool. Unless you are on an old
|
||||
// kernel or need to use an older runc version, this tool is no longer needed.
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/exeseal"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// version will be populated by the Makefile, read from
|
||||
// VERSION file of the source code.
|
||||
var version = ""
|
||||
|
||||
// gitCommit will be the hash that the binary was built from
|
||||
// and will be populated by the Makefile.
|
||||
var gitCommit = ""
|
||||
|
||||
const (
|
||||
usage = `Open Container Initiative contrib/cmd/memfd-bind
|
||||
|
||||
In order to protect against certain container attacks, every runc invocation
|
||||
that involves creating or joining a container will cause runc to make a copy of
|
||||
the runc binary in memory (usually to a memfd). While "runc init" is very
|
||||
short-lived, this extra memory usage can cause problems for containers with
|
||||
very small memory limits (or containers that have many "runc exec" invocations
|
||||
applied to them at the same time).
|
||||
|
||||
memfd-bind is a tool to create a persistent memfd-sealed-copy of the runc binary,
|
||||
which will cause runc to not make its own copy. This means you can get the
|
||||
benefits of using a sealed memfd as runc's binary (even in a container breakout
|
||||
attack to get write access to the runc binary, neither the underlying binary
|
||||
nor the memfd copy can be changed).
|
||||
|
||||
To use memfd-bind, just specify which path you want to create a socket path at
|
||||
which you want to receive terminals:
|
||||
|
||||
$ sudo memfd-bind /usr/bin/runc
|
||||
|
||||
Note that (due to kernel restrictions on bind-mounts), this program must remain
|
||||
running on the host in order for the binary to be readable (it is recommended
|
||||
you use a systemd unit to keep this process around).
|
||||
|
||||
If this program dies, there will be a leftover mountpoint that always returns
|
||||
-EINVAL when attempting to access it. You need to use memfd-bind --cleanup on the
|
||||
path in order to unmount the path (regular umount(8) will not work):
|
||||
|
||||
$ sudo memfd-bind --cleanup /usr/bin/runc
|
||||
|
||||
Note that (due to restrictions on /proc/$pid/fd/$fd magic-link resolution),
|
||||
only privileged users (specifically, those that have ptrace privileges over the
|
||||
memfd-bind daemon) can access the memfd bind-mount. This means that using this
|
||||
tool to harden your /usr/bin/runc binary would result in unprivileged users
|
||||
being unable to execute the binary. If this is an issue, you could make all
|
||||
privileged process use a different copy of runc (by making a copy in somewhere
|
||||
like /usr/sbin/runc) and only using memfd-bind for the version used by
|
||||
privileged users.
|
||||
`
|
||||
)
|
||||
|
||||
func cleanup(path string) error {
|
||||
file, err := os.OpenFile(path, unix.O_PATH|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cleanup: failed to open runc binary path: %w", err)
|
||||
}
|
||||
defer file.Close()
|
||||
fdPath := fmt.Sprintf("/proc/self/fd/%d", file.Fd())
|
||||
|
||||
// Keep umounting until we hit a umount error.
|
||||
for unix.Unmount(fdPath, unix.MNT_DETACH) == nil {
|
||||
// loop...
|
||||
logrus.Debugf("memfd-bind: path %q unmount succeeded...", path)
|
||||
}
|
||||
logrus.Infof("memfd-bind: path %q has been cleared of all old bind-mounts", path)
|
||||
return nil
|
||||
}
|
||||
|
||||
// memfdClone is a memfd-only implementation of exeseal.CloneBinary.
|
||||
func memfdClone(path string) (*os.File, error) {
|
||||
binFile, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open runc binary path: %w", err)
|
||||
}
|
||||
defer binFile.Close()
|
||||
stat, err := binFile.Stat()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("checking %s size: %w", path, err)
|
||||
}
|
||||
size := stat.Size()
|
||||
memfd, sealFn, err := exeseal.Memfd("/proc/self/exe")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating memfd failed: %w", err)
|
||||
}
|
||||
copied, err := io.Copy(memfd, binFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("copy binary: %w", err)
|
||||
} else if copied != size {
|
||||
return nil, fmt.Errorf("copied binary size mismatch: %d != %d", copied, size)
|
||||
}
|
||||
if err := sealFn(&memfd); err != nil {
|
||||
return nil, fmt.Errorf("could not seal fd: %w", err)
|
||||
}
|
||||
if !exeseal.IsCloned(memfd) {
|
||||
return nil, fmt.Errorf("cloned memfd is not properly sealed")
|
||||
}
|
||||
return memfd, nil
|
||||
}
|
||||
|
||||
func mount(path string) error {
|
||||
memfdFile, err := memfdClone(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("memfd clone: %w", err)
|
||||
}
|
||||
defer memfdFile.Close()
|
||||
memfdPath := fmt.Sprintf("/proc/self/fd/%d", memfdFile.Fd())
|
||||
|
||||
// We have to open an O_NOFOLLOW|O_PATH to the memfd magic-link because we
|
||||
// cannot bind-mount the memfd itself (it's in the internal kernel mount
|
||||
// namespace and cross-mount-namespace bind-mounts are not allowed). This
|
||||
// also requires that this program stay alive continuously for the
|
||||
// magic-link to stay alive...
|
||||
memfdLink, err := os.OpenFile(memfdPath, unix.O_PATH|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("mount: failed to /proc/self/fd magic-link for memfd: %w", err)
|
||||
}
|
||||
defer memfdLink.Close()
|
||||
memfdLinkFdPath := fmt.Sprintf("/proc/self/fd/%d", memfdLink.Fd())
|
||||
|
||||
exeFile, err := os.OpenFile(path, unix.O_PATH|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("mount: failed to open target runc binary path: %w", err)
|
||||
}
|
||||
defer exeFile.Close()
|
||||
exeFdPath := fmt.Sprintf("/proc/self/fd/%d", exeFile.Fd())
|
||||
|
||||
err = unix.Mount(memfdLinkFdPath, exeFdPath, "", unix.MS_BIND, "")
|
||||
if err != nil {
|
||||
return fmt.Errorf("mount: failed to mount memfd on top of runc binary path target: %w", err)
|
||||
}
|
||||
|
||||
// If there is a signal we want to do cleanup.
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
signal.Notify(sigCh, os.Interrupt, unix.SIGTERM, unix.SIGINT)
|
||||
go func() {
|
||||
<-sigCh
|
||||
logrus.Infof("memfd-bind: exit signal caught! cleaning up the bind-mount on %q...", path)
|
||||
_ = cleanup(path)
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
// Clean up things we don't need...
|
||||
_ = exeFile.Close()
|
||||
_ = memfdLink.Close()
|
||||
|
||||
// We now have to stay alive to keep the magic-link alive...
|
||||
logrus.Infof("memfd-bind: bind-mount of memfd over %q created -- looping forever!", path)
|
||||
for {
|
||||
// loop forever...
|
||||
time.Sleep(time.Duration(1<<63 - 1))
|
||||
// make sure the memfd isn't gc'd
|
||||
runtime.KeepAlive(memfdFile)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "memfd-bind"
|
||||
app.Usage = usage
|
||||
|
||||
// Set version to be the same as runC.
|
||||
var v []string
|
||||
if version != "" {
|
||||
v = append(v, version)
|
||||
}
|
||||
if gitCommit != "" {
|
||||
v = append(v, "commit: "+gitCommit)
|
||||
}
|
||||
app.Version = strings.Join(v, "\n")
|
||||
|
||||
// Set the flags.
|
||||
app.Flags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "cleanup",
|
||||
Usage: "Do not create a new memfd-sealed file, only clean up an existing one at <path>.",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Usage: "Enable debug logging.",
|
||||
},
|
||||
}
|
||||
|
||||
app.Action = func(ctx *cli.Context) error {
|
||||
args := ctx.Args()
|
||||
if len(args) != 1 {
|
||||
return errors.New("need to specify a single path to the runc binary")
|
||||
}
|
||||
path := ctx.Args()[0]
|
||||
|
||||
if ctx.Bool("debug") {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
|
||||
err := cleanup(path)
|
||||
// We only care about cleanup errors when doing --cleanup.
|
||||
if ctx.Bool("cleanup") {
|
||||
return err
|
||||
}
|
||||
return mount(path)
|
||||
}
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "memfd-bind: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
[Unit]
|
||||
Description=Manage memfd-bind of %f
|
||||
Documentation=https://github.com/opencontainers/runc/blob/main/contrib/cmd/memfd-bind/README.md
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=memfd-bind "%f"
|
||||
ExecStop=memfd-bind --cleanup "%f"
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,29 +0,0 @@
|
||||
package configs
|
||||
|
||||
import "github.com/opencontainers/cgroups"
|
||||
|
||||
// Deprecated: use [github.com/opencontainers/cgroups].
|
||||
type (
|
||||
Cgroup = cgroups.Cgroup
|
||||
Resources = cgroups.Resources
|
||||
FreezerState = cgroups.FreezerState
|
||||
LinuxRdma = cgroups.LinuxRdma
|
||||
BlockIODevice = cgroups.BlockIODevice
|
||||
WeightDevice = cgroups.WeightDevice
|
||||
ThrottleDevice = cgroups.ThrottleDevice
|
||||
HugepageLimit = cgroups.HugepageLimit
|
||||
IfPrioMap = cgroups.IfPrioMap
|
||||
)
|
||||
|
||||
// Deprecated: use [github.com/opencontainers/cgroups].
|
||||
const (
|
||||
Undefined = cgroups.Undefined
|
||||
Frozen = cgroups.Frozen
|
||||
Thawed = cgroups.Thawed
|
||||
)
|
||||
|
||||
// Deprecated: use [github.com/opencontainers/cgroups].
|
||||
var (
|
||||
NewWeightDevice = cgroups.NewWeightDevice
|
||||
NewThrottleDevice = cgroups.NewThrottleDevice
|
||||
)
|
||||
@@ -466,17 +466,6 @@ type Capabilities struct {
|
||||
Ambient []string `json:"Ambient,omitempty"`
|
||||
}
|
||||
|
||||
// Deprecated: use [Hooks.Run] instead.
|
||||
func (hooks HookList) RunHooks(state *specs.State) error {
|
||||
for i, h := range hooks {
|
||||
if err := h.Run(state); err != nil {
|
||||
return fmt.Errorf("error running hook #%d: %w", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hooks *Hooks) UnmarshalJSON(b []byte) error {
|
||||
var state map[HookName][]CommandHook
|
||||
|
||||
|
||||
@@ -2,25 +2,6 @@ package configs
|
||||
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
// Memory policy modes and flags as defined in /usr/include/linux/mempolicy.h
|
||||
//
|
||||
// Deprecated: use constants from [unix] instead.
|
||||
//
|
||||
//nolint:revive,staticcheck,nolintlint // ignore ALL_CAPS errors in consts from numaif.h, will match unix.* in the future
|
||||
const (
|
||||
MPOL_DEFAULT = unix.MPOL_DEFAULT
|
||||
MPOL_PREFERRED = unix.MPOL_PREFERRED
|
||||
MPOL_BIND = unix.MPOL_BIND
|
||||
MPOL_INTERLEAVE = unix.MPOL_INTERLEAVE
|
||||
MPOL_LOCAL = unix.MPOL_LOCAL
|
||||
MPOL_PREFERRED_MANY = unix.MPOL_PREFERRED_MANY
|
||||
MPOL_WEIGHTED_INTERLEAVE = unix.MPOL_WEIGHTED_INTERLEAVE
|
||||
|
||||
MPOL_F_STATIC_NODES = unix.MPOL_F_STATIC_NODES
|
||||
MPOL_F_RELATIVE_NODES = unix.MPOL_F_RELATIVE_NODES
|
||||
MPOL_F_NUMA_BALANCING = unix.MPOL_F_NUMA_BALANCING
|
||||
)
|
||||
|
||||
// LinuxMemoryPolicy contains memory policy configuration.
|
||||
type LinuxMemoryPolicy struct {
|
||||
// Mode specifies memory policy mode without mode flags. See
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package devices
|
||||
|
||||
import "github.com/opencontainers/cgroups/devices/config"
|
||||
|
||||
// Deprecated: use [github.com/opencontainers/cgroups/devices/config].
|
||||
const (
|
||||
Wildcard = config.Wildcard
|
||||
WildcardDevice = config.WildcardDevice
|
||||
BlockDevice = config.BlockDevice
|
||||
CharDevice = config.CharDevice
|
||||
FifoDevice = config.FifoDevice
|
||||
)
|
||||
|
||||
// Deprecated: use [github.com/opencontainers/cgroups/devices/config].
|
||||
type (
|
||||
Device = config.Device
|
||||
Permissions = config.Permissions
|
||||
Type = config.Type
|
||||
Rule = config.Rule
|
||||
)
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/opencontainers/cgroups/devices/config"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@@ -22,7 +23,7 @@ var (
|
||||
// DeviceFromPath takes the path to a device and its cgroup_permissions (which
|
||||
// cannot be easily queried) to look up the information about a linux device
|
||||
// and returns that information as a Device struct.
|
||||
func DeviceFromPath(path, permissions string) (*Device, error) {
|
||||
func DeviceFromPath(path, permissions string) (*config.Device, error) {
|
||||
var stat unix.Stat_t
|
||||
err := unixLstat(path, &stat)
|
||||
if err != nil {
|
||||
@@ -30,7 +31,7 @@ func DeviceFromPath(path, permissions string) (*Device, error) {
|
||||
}
|
||||
|
||||
var (
|
||||
devType Type
|
||||
devType config.Type
|
||||
mode = stat.Mode
|
||||
devNumber = uint64(stat.Rdev) //nolint:unconvert // Rdev is uint32 on e.g. MIPS.
|
||||
major = unix.Major(devNumber)
|
||||
@@ -38,20 +39,20 @@ func DeviceFromPath(path, permissions string) (*Device, error) {
|
||||
)
|
||||
switch mode & unix.S_IFMT {
|
||||
case unix.S_IFBLK:
|
||||
devType = BlockDevice
|
||||
devType = config.BlockDevice
|
||||
case unix.S_IFCHR:
|
||||
devType = CharDevice
|
||||
devType = config.CharDevice
|
||||
case unix.S_IFIFO:
|
||||
devType = FifoDevice
|
||||
devType = config.FifoDevice
|
||||
default:
|
||||
return nil, ErrNotADevice
|
||||
}
|
||||
return &Device{
|
||||
Rule: Rule{
|
||||
return &config.Device{
|
||||
Rule: config.Rule{
|
||||
Type: devType,
|
||||
Major: int64(major),
|
||||
Minor: int64(minor),
|
||||
Permissions: Permissions(permissions),
|
||||
Permissions: config.Permissions(permissions),
|
||||
},
|
||||
Path: path,
|
||||
FileMode: os.FileMode(mode &^ unix.S_IFMT),
|
||||
@@ -61,18 +62,18 @@ func DeviceFromPath(path, permissions string) (*Device, error) {
|
||||
}
|
||||
|
||||
// HostDevices returns all devices that can be found under /dev directory.
|
||||
func HostDevices() ([]*Device, error) {
|
||||
func HostDevices() ([]*config.Device, error) {
|
||||
return GetDevices("/dev")
|
||||
}
|
||||
|
||||
// GetDevices recursively traverses a directory specified by path
|
||||
// and returns all devices found there.
|
||||
func GetDevices(path string) ([]*Device, error) {
|
||||
func GetDevices(path string) ([]*config.Device, error) {
|
||||
files, err := osReadDir(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var out []*Device
|
||||
var out []*config.Device
|
||||
for _, f := range files {
|
||||
switch {
|
||||
case f.IsDir():
|
||||
@@ -103,7 +104,7 @@ func GetDevices(path string) ([]*Device, error) {
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if device.Type == FifoDevice {
|
||||
if device.Type == config.FifoDevice {
|
||||
continue
|
||||
}
|
||||
out = append(out, device)
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/opencontainers/cgroups/devices/config"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@@ -85,8 +86,8 @@ func TestHostDevicesAllValid(t *testing.T) {
|
||||
t.Errorf("device entry %+v has zero major number", device)
|
||||
}
|
||||
switch device.Type {
|
||||
case BlockDevice, CharDevice:
|
||||
case FifoDevice:
|
||||
case config.BlockDevice, config.CharDevice:
|
||||
case config.FifoDevice:
|
||||
t.Logf("fifo devices shouldn't show up from HostDevices")
|
||||
fallthrough
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user