Commit Graph

69 Commits

Author SHA1 Message Date
Nalin Dahyabhai d10c03bc3d Extend driver.ListLayers()
Implement ListLayers() for the aufs, btrfs, and devicemapper drivers,
along with a unit test for them.
Stop filtering out directories with names that aren't 64-hex chars in
vfs and overlay ListLayers() implementations, which is more a convention
than a hard rule.
Have layerStore.Wipe() try to remove remaining listed layers after it
removes the layers that the layerStore knew of.
Close() a dangling ReadCloser in NaiveCreateFromTemplate.
Switch from using plain defer to using t.Cleanup() to handle deleting
layers that tests create, have the addManyLayers() test function do so
as well.
Remove vfs.CopyDir, which near as I can tell isn't referenced anywhere.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2023-04-12 16:05:09 -04:00
Daniel J Walsh a3204cf7e8
Move to golang 1.18 and later
Github.com is reporting security issues on older versions of
golang.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2023-04-03 15:26:54 -04:00
Alexander Larsson ddf18d41da Add Store.GarbageCollect() method
This looks in the container store for existing data dirs with ids not in
the container files and removes them. It also adds an (optional) driver
method to list available layers, then uses this and compares it to the
layers json file and removes layers that are not references.

Losing track of containers and layers can potentially happen in the
case of some kind of unclean shutdown, but mainly it happens at reboot
when using transient storage mode. Such users are recommended to run
a garbage collect at boot.

Signed-off-by: Alexander Larsson <alexl@redhat.com>
2022-11-14 16:36:30 +01:00
Paul Holzinger bb74ff653c
fix inconsitent go build tags
Run `go fmt ./...` which automatically adds the new build tag syntax.
This change is backwards compatible.

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
2022-11-02 20:51:27 +01:00
Miloslav Trmač f1e256e70d Introduce, and use, graphdriver.MustRegister
... instead of silently failing.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-10-01 02:46:52 +02:00
Miloslav Trmač be12df78e9 Only build drivers/devmapper/jsoniter.go when building devmapper
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-09-12 16:31:46 +02:00
Miloslav Trmač b8f4b5f2d3 Use os.ReadDir instead of ioutil.ReadDir
That is frequently an optimization, because it avoids
a per-item lstat().

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-09-12 16:31:38 +02:00
Miloslav Trmač a1ccc9d862 Use os.WriteFile instead of ioutil.WriteFile
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-09-12 16:31:34 +02:00
Miloslav Trmač cfbc77122a Use os.CreateTemp instead of ioutil.TempFile
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-09-12 16:30:48 +02:00
Miloslav Trmač 4b28197720 Use os.ReadFile instead of ioutil.ReadFile
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-09-12 16:30:43 +02:00
Alice Frosi a010eb437c fix return error in device mapper
The function readLVMConfig always returns an error.

Signed-off-by: Alice Frosi <afrosi@redhat.com>
2022-07-25 09:51:57 +02:00
Sascha Grunert 42b530b1c3
Fix missing error check in device mapper
We missed that error check during the conversion, which is now fixed.

Signed-off-by: Sascha Grunert <sgrunert@redhat.com>
2022-07-21 12:32:42 +02:00
Daniel J Walsh 8e967aa356
Merge pull request #1286 from saschagrunert/error-wrap
Fix wrong error return value
2022-07-13 15:10:55 -04:00
Sascha Grunert 5f2d250aba
Fix wrong error return value
We now pre-check the error before returning it in wrapped state.

Signed-off-by: Sascha Grunert <sgrunert@redhat.com>
2022-07-13 13:03:35 +02:00
Daniel J Walsh 3f8c0dc0de
Wrap errors properly with fmt.Errorf
Also returned errors should not begine with a capatalized errors.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2022-07-12 13:26:10 -04:00
Sascha Grunert 3455d12729
Switch to golang native error wrapping
We now use the golang error wrapping format specifier `%w` instead of the
deprecated github.com/pkg/errors package.

Signed-off-by: Sascha Grunert <sgrunert@redhat.com>
2022-07-07 13:22:46 +02:00
Daniel J Walsh 04b2f0f741
Switch most calls to filepath.Walk to filepath.WalkDir
It is faster then Walk, when you don't need to stat every
file and directory.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2022-04-06 09:42:25 -04:00
gaohuatao 67e885a378 Fix cancel deferred remove bug
When cancel the deferred removal, if the device is already gone,
continue. According to the original logic, if the device does not exist,
an error is reported.

Signed-off-by: gaohuatao <gaohuatao@huawei.com>
2021-06-12 15:25:03 +08:00
gaohuatao 416095081c Avoid failure when unmount an unmounted mountpoint
Check if the mountpoint is mounted when unmount it to avoid failure.
If user manually run the umount command before it, the function
UnmountDevice returns an error, Although this error dose not cause the
container deletion process fail for the reason that the return value of
UnmountDevice function is not processed. However, the ERROR logs in the
log system are misleading

Signed-off-by: gaohuatao <gaohuatao@huawei.com>
2021-05-25 14:35:58 +08:00
gaohuatao 6886caeaea Expand the scope of transaction in the process of deleting device
When "docker load $image" and "docker rmi $image" commands are
repeatedly executed in the background, the dockerd daemon process is
killed. As a result, the DM device where the image resides may be
unavailable. The image can be queried, but the container fails to be
run. After function “devices.issueDiscard(info)” is executed and before
function "devices.deleteTransaction(info, syncDelete)" is executed, at
this point, dockerd daemon's withdrawal would result in dm device
discarded. Howerver, the dm device is not deleted at the same time.

Signed-off-by: gaohuatao <gaohuatao@huawei.com>
2021-05-13 00:37:02 -04:00
Nalin Dahyabhai 5ef1e9d68b Use json-iterator instead of encoding/json
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-05-06 12:24:24 -04:00
Nalin Dahyabhai 05155d9032 drivers/devmapper: default the rootfs directory to 0555
When creating a new devmapper rootfs directory, set its permissions to
0555 instead of 0755, bringing it in line with overlay.  A layer created
as a snapshot of a parent layer will already have such a directory, so
it should continue to inherit the parent's directory's permissions.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-02-24 16:44:51 -05:00
Peter Hunt 01776faaa6 drivers: add ReadWriteDiskUsage endpoint
all endpoints currently walk the directory to find the size

Signed-off-by: Peter Hunt <pehunt@redhat.com>
2021-01-28 11:57:53 -05:00
Kir Kolyshkin 68cc6d0219 devmapper: fix unit test
It has been pointed out that sometimes device mapper unit tests
fail with the following diagnostics:

> --- FAIL: TestDevmapperSetup (0.02s)
>    graphtest_unix.go:44: graphdriver: loopback attach failed
>    graphtest_unix.go:48: loopback attach failed

The root cause is the absence of udev inside the container used
for testing, which causes device nodes (/dev/loop*) to not be
created.

The test suite itself already has a workaround, but it only
creates 8 devices (loop0 till loop7). It might very well be
the case that the first few devices are already used by the
system (on my laptop 15 devices are busy).

The fix is to raise the number of devices being manually created.

[adopted from upstream commit 8663d0933439acd8.]
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-09-15 13:17:16 -07:00
Kir Kolyshkin dc65c45e2d devmapper: use unix.Unmount, log failures
1. Use unix.Unmount for it wraps the error message.

2. Always log umount failures (as warnings).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-09-15 13:13:55 -07:00
Kir Kolyshkin 5f1fa8b92d devmapper.shutdown: optimize
Move the "unmount and deactivate" code into a separate method, and
optimize it a bit:

1. Do not use filepath.Walk() as there's no requirement to recursively
   go into every directory under home/mnt; a list of directories in mnt
   is sufficient. With filepath.Walk(), in case some container will fail
   to unmount, it'll go through the whole container filesystem which is
   excessive and useless.

2. Do not use GetMounts() and do not check if a directory is mounted;
   just unmount it and ignore "not mounted" error. Note the same error
   is returned in case of wrong flags set, but as flags are hardcoded
   we can safely ignore such a case.

While at it, promote "can't unmount" log level from debug to warning.

[adopted from upstream commit f1a459229724f5e.]

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-09-15 13:03:17 -07:00
Kir Kolyshkin 4d8a93b908 devmapper cleanup: improve error msg
In case we have two errors, prefer the one from Shutdown().

[adopted from upstream commit 9d00aedebc2.]

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-09-15 12:59:54 -07:00
Kir Kolyshkin c7e322b269 devmapper/Remove(): use Rmdir, ignore errors
1. Replace EnsureRemoveAll() with Rmdir(), as here we are removing
   the container's mount point, which is already properly unmounted
   and is therefore an empty directory.

2. Ignore the Rmdir() error (but log it unless it's ENOENT). This
   is a mount point, currently unmounted (i.e. an empty directory),
   and an older kernel can return EBUSY if e.g. the mount was
   leaked to other mount namespaces.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>

[adopted from the upstream commit 732dd9b848bec70]
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-09-15 12:45:45 -07:00
Aleksa Sarai 6d06315f20 devmapper: add a test for mount leak workaround
In order to avoid reverting our fix for mount leakage in devicemapper,
add a test which checks that devicemapper's Get() and Put() cycle can
survive having a command running in an rprivate mount propagation setup
in-between. While this is quite rudimentary, it should be sufficient.

We have to skip this test for pre-3.18 kernels.

Signed-off-by: Aleksa Sarai <asarai@suse.de>

[kir@: adopted from upstream commit 1af8ea681fba1935]
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-09-15 12:34:37 -07:00
Aleksa Sarai 278bfc55ca devicemapper: remove container rootfs mountPath after umount
libdm currently has a fairly substantial DoS bug that makes certain
operations fail on a libdm device if the device has active references
through mountpoints. This is a significant problem with the advent of
mount namespaces and MS_PRIVATE, and can cause certain --volume mounts
to cause libdm to no longer be able to remove containers:

  % docker run -d --name testA busybox top
  % docker run -d --name testB -v /var/lib/docker:/docker busybox top
  % docker rm -f testA
  [fails on libdm with dm_task_run errors.]

This also solves the problem of unprivileged users being able to DoS
docker by using unprivileged mount namespaces to preseve mounts that
Docker has dropped.

Signed-off-by: Aleksa Sarai <asarai@suse.de>

[picked from upstream commit: 92e45b81e0a]
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-09-15 12:24:57 -07:00
Reinhard Tartler 086943ac54
unbreak build on mipsen harder
Stat_t on MIPS uses 32-bit fields for Dev and Rdev, so we need to cast these to uint64

Turns out the change in 07171909b0
is incomplete and an additional line needs a cast.

Inpiration from moby/moby#37490
Example build failure log: https://buildd.debian.org/status/fetch.php?pkg=golang-github-containers-storage&arch=mips64el&ver=1.20.2-1&stamp=1594477648&raw=0Signed-off-by: Reinhard Tartler <siretart@tauware.de>
2020-07-19 15:23:53 -04:00
Daniel J Walsh f76d8a7277
Store the pvcreate --metadatasize option in storage.conf
As the number of devices increase the size of the metadata
needs to be modified.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-07-01 05:27:31 -04:00
Michael McCracken de6e0b0236 devmapper: allow devmapper devices as directlvm device
LVM allows creating a PV on top of an LV, but resolving symlinks
before checking the output of lvmdiskscan erroneously reports that an
LV is not an available device. It will resolve an LV's name into
/dev/dm-NN, which won't show up in lvmdiskscan.

Instead this patch looks for both names in lvmdiskscan.

Signed-off-by: Michael McCracken <mikmccra@cisco.com>
2020-06-18 09:26:06 -07:00
Reinhard Tartler 07171909b0 unbreak build on mipsen
Stat_t on MIPS uses 32-bit fields for Dev and Rdev, so we need to cast these to uint64

Inpiration from https://github.com/moby/moby/pull/37490
Example build failure log: https://buildd.debian.org/status/fetch.php?pkg=golang-github-containers-storage&arch=mips64el&ver=1.15.8%2Bdfsg1-1&stamp=1580872314&raw=0

Signed-off-by: Reinhard Tartler <siretart@tauware.de>
2020-05-26 07:32:59 -04:00
Kir Kolyshkin 5124860f40 Fix MkdirAll usage
This subtle bug keeps lurking in because error checking for `Mkdir()`
and `MkdirAll()` is slightly different wrt `EEXIST`/`IsExist`:

 - for `Mkdir()`, `IsExist` error should (usually) be ignored
   (unless you want to make sure directory was not there before)
   as it means "the destination directory was already there";

 - for `MkdirAll()`, `IsExist` error should NEVER be ignored.

This commit removes ignoring the IsExist error, as it should not
be ignored.

For more details, a quote from my opencontainers/runc#162 (July 2015):

-quote-

TL;DR: check for IsExist(err) after a failed MkdirAll() is both
redundant and wrong -- so two reasons to remove it.

Quoting MkdirAll documentation:

MkdirAll creates a directory named path, along with any necessary
parents, and returns nil, or else returns an error. If path
is already a directory, MkdirAll does nothing and returns nil.

This means two things:

If a directory to be created already exists, no error is
returned.

If the error returned is IsExist (EEXIST), it means there exists
a non-directory with the same name as MkdirAll need to use for
directory. Example: we want to MkdirAll("a/b"), but file "a"
(or "a/b") already exists, so MkdirAll fails.

The above is a theory, based on quoted documentation and my UNIX
knowledge.

In practice, though, current MkdirAll implementation [1] returns
ENOTDIR in most of cases described in #2, with the exception when
there is a race between MkdirAll and someone else creating the
last component of MkdirAll argument as a file. In this very case
MkdirAll() will indeed return EEXIST.
Because of #1, IsExist check after MkdirAll is not needed.

Because of #2 and #3, ignoring IsExist error is just plain wrong,
as directory we require is not created. It's cleaner to report
the error now.

Note this error is all over the tree, I guess due to copy-paste,
or trying to follow the same usage pattern as for Mkdir(),
or some not quite correct examples on the Internet.

[1] https://github.com/golang/go/blob/f9ed2f75/src/os/path.go

-end-quote-

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-05-18 07:18:00 -07:00
Kir Kolyshkin d778a0a2ec devmapper: no need to wrap Mount errors
With the previous patch, Mount error is now verbose enough
so we don't have to supply all the gory details.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2020-03-10 06:41:39 -07:00
Sascha Grunert d88ef6dc08
Enable goimports linter and fix lints
Signed-off-by: Sascha Grunert <sgrunert@suse.com>
2020-01-28 15:59:15 +01:00
Sascha Grunert b66d5a5c12
Enable goconst linter and fix lints
Signed-off-by: Sascha Grunert <sgrunert@suse.com>
2020-01-28 15:59:15 +01:00
Nalin Dahyabhai ba598e19f2 Disable cgo-requiring bits when cgo is not enabled
Adjust build tags in drivers and pkg so that builds with CGO_ENABLED=0
won't fail outright.  This ends up disabling btrfs (which uses kernel
headers), ostree (which uses libostree), overlayfs (which uses C headers
to define fs_disk_quota_t), and devicemapper (which uses libdevmapper
and loopback) by default.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2019-08-05 13:42:50 -04:00
Nalin Dahyabhai 026db3c2bd drivers: make Init() take a graphdriver.Config
Instead of passing the driver-specific directory and assorted fields
from a Config struct to lower-level drivers when we initialize them,
pass them the directory and the Config struct.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2019-06-20 11:38:33 -04:00
Daniel J Walsh ef42340c2e
Revert "Add MountTempFromSource and RemoveTemp interfaces"
This reverts commit e9695564db.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2019-05-02 11:54:55 -04:00
Daniel J Walsh e9695564db
Add MountTempFromSource and RemoveTemp interfaces
These interfaces can be used to setup a graphdriver mountpoint
of the source directory for use within a container.
The RemoveTemp interface umounts the mountpoint and then removes
all of the modified data in the graphdriver for this source directory.

The primary use case of these interfaces is for container engines that
want to mount a directory from the host system into the container. The
source dirctory then can be modified without actually changing the
directory on the host.

Containers will use these interfaces for sharing packaing cache directories
like /var/cache/dnf, to help speed up container builds.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2019-04-29 14:46:40 -04:00
Daniel J Walsh ab043e226b
Evaluate device path for lvm
We have a bug report where a user specified a symbolic link to storage
driver.  The issue is the physical device is not predictable but the link
is, so evaluating sym links makes the symlink path supportable.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2019-04-15 05:57:51 -04:00
Nalin Dahyabhai c073b43547 Add a CreateFromTemplate() method to drivers, and use it for mapped layers
Add a CreateFromTemplate() method to graph drivers, and use it instead
of a driver-oblivious diff/put method when we want to create a copy of
an image's top layer that has the same parent and which differs from the
original only in its ID maps.

This lets drivers that can quickly make an independent layer based on
another layer do something smarter than we were doing with the
driver-oblivious method.  For some drivers, a native method is
dramatically faster.

Note that the driver needs to be able to do this while still exposing
just one notional layer (i.e., one link in the chain of layers for a
given container) to the higher levels of the APIs, so if the new layer
is actually a child of the template layer, that needs to remain a detail
that's private to the driver.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2019-01-17 14:28:40 -05:00
Nalin Dahyabhai a592151822 devicemapper: mention dm.directlvm_device in its error message
Mention the dm.directlvm_device option in the error message that we
return when it isn't set.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2018-12-06 13:50:38 -05:00
Daniel J Walsh 41f2d1cd87 Fix broken sprintf
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2018-12-04 18:27:22 -05:00
Daniel J Walsh ab6be50561
Allow the passing in and retrieval of mount options
We want to allow tools like podman/buildah to override default storage
container mount options on a container by container basis.

For example if the default mount options for containers/storage include
nodev or nosuid, we want to allow podman to turn these off if the user
specifies --privileged.

We also might want to turn off certain user namespace flags that will cause
buildah and podman build to work slower when creating container images.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2018-11-19 19:14:21 -05:00
Daniel J Walsh b6ccc0acfa
Add MountOpts to stop adding fields to Get Interface
This patch adds a MountOpts field to the drivers so we can simplify
the interface to Get and allow additional options to be passed in the future.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2018-10-05 09:23:46 -04:00
Giuseppe Scrivano 1897396330
drivers: inform Mount of the mappings used by the container
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2018-07-26 06:12:42 +02:00
Daniel J Walsh 8b1a0f8d68
Add default mount options to pass to drivers
I believe we should be running container images mounted with nodev by default.
This would eliminate the disk of a device sneaking into the container without
being on the approved list.  This would give us the same or potentially additional
security over the device cgroup.

It would be nice if this could be passed in on an image by image basis.  So users
could also specify if they want nosuid images.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2018-07-18 10:20:27 -04:00