overlay2 no longer sets `archive.OverlayWhiteoutFormat` when
running in UserNS, so we can remove the complicated logic in the
archive package.
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
(cherry picked from commit 6322dfc217a3c28ea4d7c66f43394146b3862801)
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
| ... | ... |
@@ -15,7 +15,6 @@ import ( |
| 15 | 15 |
"strings" |
| 16 | 16 |
"sync" |
| 17 | 17 |
|
| 18 |
- "github.com/containerd/containerd/sys" |
|
| 19 | 18 |
"github.com/docker/docker/daemon/graphdriver" |
| 20 | 19 |
"github.com/docker/docker/daemon/graphdriver/overlayutils" |
| 21 | 20 |
"github.com/docker/docker/pkg/archive" |
| ... | ... |
@@ -682,6 +681,7 @@ func (d *Driver) ApplyDiff(id string, parent string, diff io.Reader) (size int64 |
| 682 | 682 |
return d.naiveDiff.ApplyDiff(id, parent, diff) |
| 683 | 683 |
} |
| 684 | 684 |
|
| 685 |
+ // never reach here if we are running in UserNS |
|
| 685 | 686 |
applyDir := d.getDiffPath(id) |
| 686 | 687 |
|
| 687 | 688 |
logger.Debugf("Applying tar in %s", applyDir)
|
| ... | ... |
@@ -690,7 +690,6 @@ func (d *Driver) ApplyDiff(id string, parent string, diff io.Reader) (size int64 |
| 690 | 690 |
UIDMaps: d.uidMaps, |
| 691 | 691 |
GIDMaps: d.gidMaps, |
| 692 | 692 |
WhiteoutFormat: archive.OverlayWhiteoutFormat, |
| 693 |
- InUserNS: sys.RunningInUserNS(), |
|
| 694 | 693 |
}); err != nil {
|
| 695 | 694 |
return 0, err |
| 696 | 695 |
} |
| ... | ... |
@@ -721,6 +720,7 @@ func (d *Driver) Diff(id, parent string) (io.ReadCloser, error) {
|
| 721 | 721 |
return d.naiveDiff.Diff(id, parent) |
| 722 | 722 |
} |
| 723 | 723 |
|
| 724 |
+ // never reach here if we are running in UserNS |
|
| 724 | 725 |
diffPath := d.getDiffPath(id) |
| 725 | 726 |
logger.Debugf("Tar with options on %s", diffPath)
|
| 726 | 727 |
return archive.TarWithOptions(diffPath, &archive.TarOptions{
|
| ... | ... |
@@ -739,13 +739,18 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error) |
| 739 | 739 |
return nil, err |
| 740 | 740 |
} |
| 741 | 741 |
|
| 742 |
+ whiteoutConverter, err := getWhiteoutConverter(options.WhiteoutFormat, options.InUserNS) |
|
| 743 |
+ if err != nil {
|
|
| 744 |
+ return nil, err |
|
| 745 |
+ } |
|
| 746 |
+ |
|
| 742 | 747 |
go func() {
|
| 743 | 748 |
ta := newTarAppender( |
| 744 | 749 |
idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps), |
| 745 | 750 |
compressWriter, |
| 746 | 751 |
options.ChownOpts, |
| 747 | 752 |
) |
| 748 |
- ta.WhiteoutConverter = getWhiteoutConverter(options.WhiteoutFormat, options.InUserNS) |
|
| 753 |
+ ta.WhiteoutConverter = whiteoutConverter |
|
| 749 | 754 |
|
| 750 | 755 |
defer func() {
|
| 751 | 756 |
// Make sure to check the error on Close. |
| ... | ... |
@@ -903,7 +908,10 @@ func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) err |
| 903 | 903 |
var dirs []*tar.Header |
| 904 | 904 |
idMapping := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps) |
| 905 | 905 |
rootIDs := idMapping.RootPair() |
| 906 |
- whiteoutConverter := getWhiteoutConverter(options.WhiteoutFormat, options.InUserNS) |
|
| 906 |
+ whiteoutConverter, err := getWhiteoutConverter(options.WhiteoutFormat, options.InUserNS) |
|
| 907 |
+ if err != nil {
|
|
| 908 |
+ return err |
|
| 909 |
+ } |
|
| 907 | 910 |
|
| 908 | 911 |
// Iterate through the files in the archive. |
| 909 | 912 |
loop: |
| ... | ... |
@@ -2,29 +2,26 @@ package archive // import "github.com/docker/docker/pkg/archive" |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"archive/tar" |
| 5 |
- "fmt" |
|
| 6 |
- "io/ioutil" |
|
| 7 | 5 |
"os" |
| 8 | 6 |
"path/filepath" |
| 9 | 7 |
"strings" |
| 10 |
- "syscall" |
|
| 11 | 8 |
|
| 12 |
- "github.com/containerd/continuity/fs" |
|
| 13 | 9 |
"github.com/docker/docker/pkg/system" |
| 14 |
- "github.com/moby/sys/mount" |
|
| 15 | 10 |
"github.com/pkg/errors" |
| 16 | 11 |
"golang.org/x/sys/unix" |
| 17 | 12 |
) |
| 18 | 13 |
|
| 19 |
-func getWhiteoutConverter(format WhiteoutFormat, inUserNS bool) tarWhiteoutConverter {
|
|
| 14 |
+func getWhiteoutConverter(format WhiteoutFormat, inUserNS bool) (tarWhiteoutConverter, error) {
|
|
| 20 | 15 |
if format == OverlayWhiteoutFormat {
|
| 21 |
- return overlayWhiteoutConverter{inUserNS: inUserNS}
|
|
| 16 |
+ if inUserNS {
|
|
| 17 |
+ return nil, errors.New("specifying OverlayWhiteoutFormat is not allowed in userns")
|
|
| 18 |
+ } |
|
| 19 |
+ return overlayWhiteoutConverter{}, nil
|
|
| 22 | 20 |
} |
| 23 |
- return nil |
|
| 21 |
+ return nil, nil |
|
| 24 | 22 |
} |
| 25 | 23 |
|
| 26 | 24 |
type overlayWhiteoutConverter struct {
|
| 27 |
- inUserNS bool |
|
| 28 | 25 |
} |
| 29 | 26 |
|
| 30 | 27 |
func (overlayWhiteoutConverter) ConvertWrite(hdr *tar.Header, path string, fi os.FileInfo) (wo *tar.Header, err error) {
|
| ... | ... |
@@ -77,13 +74,7 @@ func (c overlayWhiteoutConverter) ConvertRead(hdr *tar.Header, path string) (boo |
| 77 | 77 |
if base == WhiteoutOpaqueDir {
|
| 78 | 78 |
err := unix.Setxattr(dir, "trusted.overlay.opaque", []byte{'y'}, 0)
|
| 79 | 79 |
if err != nil {
|
| 80 |
- if c.inUserNS {
|
|
| 81 |
- if err = replaceDirWithOverlayOpaque(dir); err != nil {
|
|
| 82 |
- return false, errors.Wrapf(err, "replaceDirWithOverlayOpaque(%q) failed", dir) |
|
| 83 |
- } |
|
| 84 |
- } else {
|
|
| 85 |
- return false, errors.Wrapf(err, "setxattr(%q, trusted.overlay.opaque=y)", dir) |
|
| 86 |
- } |
|
| 80 |
+ return false, errors.Wrapf(err, "setxattr(%q, trusted.overlay.opaque=y)", dir) |
|
| 87 | 81 |
} |
| 88 | 82 |
// don't write the file itself |
| 89 | 83 |
return false, err |
| ... | ... |
@@ -95,19 +86,7 @@ func (c overlayWhiteoutConverter) ConvertRead(hdr *tar.Header, path string) (boo |
| 95 | 95 |
originalPath := filepath.Join(dir, originalBase) |
| 96 | 96 |
|
| 97 | 97 |
if err := unix.Mknod(originalPath, unix.S_IFCHR, 0); err != nil {
|
| 98 |
- if c.inUserNS {
|
|
| 99 |
- // Ubuntu and a few distros support overlayfs in userns. |
|
| 100 |
- // |
|
| 101 |
- // Although we can't call mknod directly in userns (at least on bionic kernel 4.15), |
|
| 102 |
- // we can still create 0,0 char device using mknodChar0Overlay(). |
|
| 103 |
- // |
|
| 104 |
- // NOTE: we don't need this hack for the containerd snapshotter+unpack model. |
|
| 105 |
- if err := mknodChar0Overlay(originalPath); err != nil {
|
|
| 106 |
- return false, errors.Wrapf(err, "failed to mknodChar0UserNS(%q)", originalPath) |
|
| 107 |
- } |
|
| 108 |
- } else {
|
|
| 109 |
- return false, errors.Wrapf(err, "failed to mknod(%q, S_IFCHR, 0)", originalPath) |
|
| 110 |
- } |
|
| 98 |
+ return false, errors.Wrapf(err, "failed to mknod(%q, S_IFCHR, 0)", originalPath) |
|
| 111 | 99 |
} |
| 112 | 100 |
if err := os.Chown(originalPath, hdr.Uid, hdr.Gid); err != nil {
|
| 113 | 101 |
return false, err |
| ... | ... |
@@ -119,146 +98,3 @@ func (c overlayWhiteoutConverter) ConvertRead(hdr *tar.Header, path string) (boo |
| 119 | 119 |
|
| 120 | 120 |
return true, nil |
| 121 | 121 |
} |
| 122 |
- |
|
| 123 |
-// mknodChar0Overlay creates 0,0 char device by mounting overlayfs and unlinking. |
|
| 124 |
-// This function can be used for creating 0,0 char device in userns on Ubuntu. |
|
| 125 |
-// |
|
| 126 |
-// Steps: |
|
| 127 |
-// * Mkdir lower,upper,merged,work |
|
| 128 |
-// * Create lower/dummy |
|
| 129 |
-// * Mount overlayfs |
|
| 130 |
-// * Unlink merged/dummy |
|
| 131 |
-// * Unmount overlayfs |
|
| 132 |
-// * Make sure a 0,0 char device is created as upper/dummy |
|
| 133 |
-// * Rename upper/dummy to cleansedOriginalPath |
|
| 134 |
-func mknodChar0Overlay(cleansedOriginalPath string) error {
|
|
| 135 |
- dir := filepath.Dir(cleansedOriginalPath) |
|
| 136 |
- tmp, err := ioutil.TempDir(dir, "mc0o") |
|
| 137 |
- if err != nil {
|
|
| 138 |
- return errors.Wrapf(err, "failed to create a tmp directory under %s", dir) |
|
| 139 |
- } |
|
| 140 |
- defer os.RemoveAll(tmp) |
|
| 141 |
- lower := filepath.Join(tmp, "l") |
|
| 142 |
- upper := filepath.Join(tmp, "u") |
|
| 143 |
- work := filepath.Join(tmp, "w") |
|
| 144 |
- merged := filepath.Join(tmp, "m") |
|
| 145 |
- for _, s := range []string{lower, upper, work, merged} {
|
|
| 146 |
- if err := os.MkdirAll(s, 0700); err != nil {
|
|
| 147 |
- return errors.Wrapf(err, "failed to mkdir %s", s) |
|
| 148 |
- } |
|
| 149 |
- } |
|
| 150 |
- dummyBase := "d" |
|
| 151 |
- lowerDummy := filepath.Join(lower, dummyBase) |
|
| 152 |
- if err := ioutil.WriteFile(lowerDummy, []byte{}, 0600); err != nil {
|
|
| 153 |
- return errors.Wrapf(err, "failed to create a dummy lower file %s", lowerDummy) |
|
| 154 |
- } |
|
| 155 |
- // lowerdir needs ":" to be escaped: https://github.com/moby/moby/issues/40939#issuecomment-627098286 |
|
| 156 |
- lowerEscaped := strings.ReplaceAll(lower, ":", "\\:") |
|
| 157 |
- mOpts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lowerEscaped, upper, work)
|
|
| 158 |
- if err := mount.Mount("overlay", merged, "overlay", mOpts); err != nil {
|
|
| 159 |
- return err |
|
| 160 |
- } |
|
| 161 |
- mergedDummy := filepath.Join(merged, dummyBase) |
|
| 162 |
- if err := os.Remove(mergedDummy); err != nil {
|
|
| 163 |
- syscall.Unmount(merged, 0) |
|
| 164 |
- return errors.Wrapf(err, "failed to unlink %s", mergedDummy) |
|
| 165 |
- } |
|
| 166 |
- if err := syscall.Unmount(merged, 0); err != nil {
|
|
| 167 |
- return errors.Wrapf(err, "failed to unmount %s", merged) |
|
| 168 |
- } |
|
| 169 |
- upperDummy := filepath.Join(upper, dummyBase) |
|
| 170 |
- if err := isChar0(upperDummy); err != nil {
|
|
| 171 |
- return err |
|
| 172 |
- } |
|
| 173 |
- if err := os.Rename(upperDummy, cleansedOriginalPath); err != nil {
|
|
| 174 |
- return errors.Wrapf(err, "failed to rename %s to %s", upperDummy, cleansedOriginalPath) |
|
| 175 |
- } |
|
| 176 |
- return nil |
|
| 177 |
-} |
|
| 178 |
- |
|
| 179 |
-func isChar0(path string) error {
|
|
| 180 |
- osStat, err := os.Stat(path) |
|
| 181 |
- if err != nil {
|
|
| 182 |
- return errors.Wrapf(err, "failed to stat %s", path) |
|
| 183 |
- } |
|
| 184 |
- st, ok := osStat.Sys().(*syscall.Stat_t) |
|
| 185 |
- if !ok {
|
|
| 186 |
- return errors.Errorf("got unsupported stat for %s", path)
|
|
| 187 |
- } |
|
| 188 |
- if os.FileMode(st.Mode)&syscall.S_IFMT != syscall.S_IFCHR {
|
|
| 189 |
- return errors.Errorf("%s is not a character device, got mode=%d", path, st.Mode)
|
|
| 190 |
- } |
|
| 191 |
- if st.Rdev != 0 {
|
|
| 192 |
- return errors.Errorf("%s is not a 0,0 character device, got Rdev=%d", path, st.Rdev)
|
|
| 193 |
- } |
|
| 194 |
- return nil |
|
| 195 |
-} |
|
| 196 |
- |
|
| 197 |
-// replaceDirWithOverlayOpaque replaces path with a new directory with trusted.overlay.opaque |
|
| 198 |
-// xattr. The contents of the directory are preserved. |
|
| 199 |
-func replaceDirWithOverlayOpaque(path string) error {
|
|
| 200 |
- if path == "/" {
|
|
| 201 |
- return errors.New("replaceDirWithOverlayOpaque: path must not be \"/\"")
|
|
| 202 |
- } |
|
| 203 |
- dir := filepath.Dir(path) |
|
| 204 |
- tmp, err := ioutil.TempDir(dir, "rdwoo") |
|
| 205 |
- if err != nil {
|
|
| 206 |
- return errors.Wrapf(err, "failed to create a tmp directory under %s", dir) |
|
| 207 |
- } |
|
| 208 |
- defer os.RemoveAll(tmp) |
|
| 209 |
- // newPath is a new empty directory crafted with trusted.overlay.opaque xattr. |
|
| 210 |
- // we copy the content of path into newPath, remove path, and rename newPath to path. |
|
| 211 |
- newPath, err := createDirWithOverlayOpaque(tmp) |
|
| 212 |
- if err != nil {
|
|
| 213 |
- return errors.Wrapf(err, "createDirWithOverlayOpaque(%q) failed", tmp) |
|
| 214 |
- } |
|
| 215 |
- if err := fs.CopyDir(newPath, path); err != nil {
|
|
| 216 |
- return errors.Wrapf(err, "CopyDir(%q, %q) failed", newPath, path) |
|
| 217 |
- } |
|
| 218 |
- if err := os.RemoveAll(path); err != nil {
|
|
| 219 |
- return err |
|
| 220 |
- } |
|
| 221 |
- return os.Rename(newPath, path) |
|
| 222 |
-} |
|
| 223 |
- |
|
| 224 |
-// createDirWithOverlayOpaque creates a directory with trusted.overlay.opaque xattr, |
|
| 225 |
-// without calling setxattr, so as to allow creating opaque dir in userns on Ubuntu. |
|
| 226 |
-func createDirWithOverlayOpaque(tmp string) (string, error) {
|
|
| 227 |
- lower := filepath.Join(tmp, "l") |
|
| 228 |
- upper := filepath.Join(tmp, "u") |
|
| 229 |
- work := filepath.Join(tmp, "w") |
|
| 230 |
- merged := filepath.Join(tmp, "m") |
|
| 231 |
- for _, s := range []string{lower, upper, work, merged} {
|
|
| 232 |
- if err := os.MkdirAll(s, 0700); err != nil {
|
|
| 233 |
- return "", errors.Wrapf(err, "failed to mkdir %s", s) |
|
| 234 |
- } |
|
| 235 |
- } |
|
| 236 |
- dummyBase := "d" |
|
| 237 |
- lowerDummy := filepath.Join(lower, dummyBase) |
|
| 238 |
- if err := os.MkdirAll(lowerDummy, 0700); err != nil {
|
|
| 239 |
- return "", errors.Wrapf(err, "failed to create a dummy lower directory %s", lowerDummy) |
|
| 240 |
- } |
|
| 241 |
- // lowerdir needs ":" to be escaped: https://github.com/moby/moby/issues/40939#issuecomment-627098286 |
|
| 242 |
- lowerEscaped := strings.ReplaceAll(lower, ":", "\\:") |
|
| 243 |
- mOpts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lowerEscaped, upper, work)
|
|
| 244 |
- if err := mount.Mount("overlay", merged, "overlay", mOpts); err != nil {
|
|
| 245 |
- return "", err |
|
| 246 |
- } |
|
| 247 |
- mergedDummy := filepath.Join(merged, dummyBase) |
|
| 248 |
- if err := os.Remove(mergedDummy); err != nil {
|
|
| 249 |
- syscall.Unmount(merged, 0) |
|
| 250 |
- return "", errors.Wrapf(err, "failed to rmdir %s", mergedDummy) |
|
| 251 |
- } |
|
| 252 |
- // upperDummy becomes a 0,0-char device file here |
|
| 253 |
- if err := os.Mkdir(mergedDummy, 0700); err != nil {
|
|
| 254 |
- syscall.Unmount(merged, 0) |
|
| 255 |
- return "", errors.Wrapf(err, "failed to mkdir %s", mergedDummy) |
|
| 256 |
- } |
|
| 257 |
- // upperDummy becomes a directory with trusted.overlay.opaque xattr |
|
| 258 |
- // (but can't be verified in userns) |
|
| 259 |
- if err := syscall.Unmount(merged, 0); err != nil {
|
|
| 260 |
- return "", errors.Wrapf(err, "failed to unmount %s", merged) |
|
| 261 |
- } |
|
| 262 |
- upperDummy := filepath.Join(upper, dummyBase) |
|
| 263 |
- return upperDummy, nil |
|
| 264 |
-} |
| ... | ... |
@@ -1,19 +1,14 @@ |
| 1 | 1 |
package archive // import "github.com/docker/docker/pkg/archive" |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
- "fmt" |
|
| 5 | 4 |
"io/ioutil" |
| 6 | 5 |
"os" |
| 7 |
- "os/exec" |
|
| 8 | 6 |
"path/filepath" |
| 9 | 7 |
"syscall" |
| 10 | 8 |
"testing" |
| 11 | 9 |
|
| 12 | 10 |
"github.com/containerd/containerd/sys" |
| 13 |
- "github.com/docker/docker/pkg/reexec" |
|
| 14 | 11 |
"github.com/docker/docker/pkg/system" |
| 15 |
- "github.com/moby/sys/mount" |
|
| 16 |
- "github.com/pkg/errors" |
|
| 17 | 12 |
"golang.org/x/sys/unix" |
| 18 | 13 |
"gotest.tools/v3/assert" |
| 19 | 14 |
"gotest.tools/v3/skip" |
| ... | ... |
@@ -167,129 +162,3 @@ func TestOverlayTarAUFSUntar(t *testing.T) {
|
| 167 | 167 |
checkFileMode(t, filepath.Join(dst, "d2", "f1"), 0660) |
| 168 | 168 |
checkFileMode(t, filepath.Join(dst, "d3", WhiteoutPrefix+"f1"), 0600) |
| 169 | 169 |
} |
| 170 |
- |
|
| 171 |
-func unshareCmd(cmd *exec.Cmd) {
|
|
| 172 |
- cmd.SysProcAttr = &syscall.SysProcAttr{
|
|
| 173 |
- Cloneflags: syscall.CLONE_NEWUSER | syscall.CLONE_NEWNS, |
|
| 174 |
- UidMappings: []syscall.SysProcIDMap{
|
|
| 175 |
- {
|
|
| 176 |
- ContainerID: 0, |
|
| 177 |
- HostID: os.Geteuid(), |
|
| 178 |
- Size: 1, |
|
| 179 |
- }, |
|
| 180 |
- }, |
|
| 181 |
- GidMappings: []syscall.SysProcIDMap{
|
|
| 182 |
- {
|
|
| 183 |
- ContainerID: 0, |
|
| 184 |
- HostID: os.Getegid(), |
|
| 185 |
- Size: 1, |
|
| 186 |
- }, |
|
| 187 |
- }, |
|
| 188 |
- } |
|
| 189 |
-} |
|
| 190 |
- |
|
| 191 |
-const ( |
|
| 192 |
- reexecSupportsUserNSOverlay = "docker-test-supports-userns-overlay" |
|
| 193 |
- reexecMknodChar0 = "docker-test-userns-mknod-char0" |
|
| 194 |
- reexecSetOpaque = "docker-test-userns-set-opaque" |
|
| 195 |
-) |
|
| 196 |
- |
|
| 197 |
-func supportsOverlay(dir string) error {
|
|
| 198 |
- lower := filepath.Join(dir, "l") |
|
| 199 |
- upper := filepath.Join(dir, "u") |
|
| 200 |
- work := filepath.Join(dir, "w") |
|
| 201 |
- merged := filepath.Join(dir, "m") |
|
| 202 |
- for _, s := range []string{lower, upper, work, merged} {
|
|
| 203 |
- if err := os.MkdirAll(s, 0700); err != nil {
|
|
| 204 |
- return err |
|
| 205 |
- } |
|
| 206 |
- } |
|
| 207 |
- mOpts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lower, upper, work)
|
|
| 208 |
- if err := mount.Mount("overlay", merged, "overlay", mOpts); err != nil {
|
|
| 209 |
- return err |
|
| 210 |
- } |
|
| 211 |
- if err := mount.Unmount(merged); err != nil {
|
|
| 212 |
- return err |
|
| 213 |
- } |
|
| 214 |
- return nil |
|
| 215 |
-} |
|
| 216 |
- |
|
| 217 |
-// supportsUserNSOverlay returns nil error if overlay is supported in userns. |
|
| 218 |
-// Only Ubuntu and a few distros support overlay in userns (by patching the kernel). |
|
| 219 |
-// https://lists.ubuntu.com/archives/kernel-team/2014-February/038091.html |
|
| 220 |
-// As of kernel 4.19, the patch is not merged to the upstream. |
|
| 221 |
-func supportsUserNSOverlay() error {
|
|
| 222 |
- tmp, err := ioutil.TempDir("", "docker-test-supports-userns-overlay")
|
|
| 223 |
- if err != nil {
|
|
| 224 |
- return err |
|
| 225 |
- } |
|
| 226 |
- defer os.RemoveAll(tmp) |
|
| 227 |
- cmd := reexec.Command(reexecSupportsUserNSOverlay, tmp) |
|
| 228 |
- unshareCmd(cmd) |
|
| 229 |
- out, err := cmd.CombinedOutput() |
|
| 230 |
- if err != nil {
|
|
| 231 |
- return errors.Wrapf(err, "output: %q", string(out)) |
|
| 232 |
- } |
|
| 233 |
- return nil |
|
| 234 |
-} |
|
| 235 |
- |
|
| 236 |
-// isOpaque returns nil error if the dir has trusted.overlay.opaque=y. |
|
| 237 |
-// isOpaque needs to be called in the initial userns. |
|
| 238 |
-func isOpaque(dir string) error {
|
|
| 239 |
- xattrOpaque, err := system.Lgetxattr(dir, "trusted.overlay.opaque") |
|
| 240 |
- if err != nil {
|
|
| 241 |
- return errors.Wrapf(err, "failed to read opaque flag of %s", dir) |
|
| 242 |
- } |
|
| 243 |
- if string(xattrOpaque) != "y" {
|
|
| 244 |
- return errors.Errorf("expected \"y\", got %q", string(xattrOpaque))
|
|
| 245 |
- } |
|
| 246 |
- return nil |
|
| 247 |
-} |
|
| 248 |
- |
|
| 249 |
-func TestReexecUserNSOverlayWhiteoutConverter(t *testing.T) {
|
|
| 250 |
- skip.If(t, os.Getuid() != 0, "skipping test that requires root") |
|
| 251 |
- skip.If(t, sys.RunningInUserNS(), "skipping test that requires initial userns") |
|
| 252 |
- if err := supportsUserNSOverlay(); err != nil {
|
|
| 253 |
- t.Skipf("skipping test that requires kernel support for overlay-in-userns: %v", err)
|
|
| 254 |
- } |
|
| 255 |
- tmp, err := ioutil.TempDir("", "docker-test-userns-overlay")
|
|
| 256 |
- assert.NilError(t, err) |
|
| 257 |
- defer os.RemoveAll(tmp) |
|
| 258 |
- |
|
| 259 |
- char0 := filepath.Join(tmp, "char0") |
|
| 260 |
- cmd := reexec.Command(reexecMknodChar0, char0) |
|
| 261 |
- unshareCmd(cmd) |
|
| 262 |
- out, err := cmd.CombinedOutput() |
|
| 263 |
- assert.NilError(t, err, string(out)) |
|
| 264 |
- assert.NilError(t, isChar0(char0)) |
|
| 265 |
- |
|
| 266 |
- opaqueDir := filepath.Join(tmp, "opaquedir") |
|
| 267 |
- err = os.MkdirAll(opaqueDir, 0755) |
|
| 268 |
- assert.NilError(t, err, string(out)) |
|
| 269 |
- cmd = reexec.Command(reexecSetOpaque, opaqueDir) |
|
| 270 |
- unshareCmd(cmd) |
|
| 271 |
- out, err = cmd.CombinedOutput() |
|
| 272 |
- assert.NilError(t, err, string(out)) |
|
| 273 |
- assert.NilError(t, isOpaque(opaqueDir)) |
|
| 274 |
-} |
|
| 275 |
- |
|
| 276 |
-func init() {
|
|
| 277 |
- reexec.Register(reexecSupportsUserNSOverlay, func() {
|
|
| 278 |
- if err := supportsOverlay(os.Args[1]); err != nil {
|
|
| 279 |
- panic(err) |
|
| 280 |
- } |
|
| 281 |
- }) |
|
| 282 |
- reexec.Register(reexecMknodChar0, func() {
|
|
| 283 |
- if err := mknodChar0Overlay(os.Args[1]); err != nil {
|
|
| 284 |
- panic(err) |
|
| 285 |
- } |
|
| 286 |
- }) |
|
| 287 |
- reexec.Register(reexecSetOpaque, func() {
|
|
| 288 |
- if err := replaceDirWithOverlayOpaque(os.Args[1]); err != nil {
|
|
| 289 |
- panic(err) |
|
| 290 |
- } |
|
| 291 |
- }) |
|
| 292 |
- if reexec.Init() {
|
|
| 293 |
- os.Exit(0) |
|
| 294 |
- } |
|
| 295 |
-} |
| ... | ... |
@@ -2,6 +2,6 @@ |
| 2 | 2 |
|
| 3 | 3 |
package archive // import "github.com/docker/docker/pkg/archive" |
| 4 | 4 |
|
| 5 |
-func getWhiteoutConverter(format WhiteoutFormat, inUserNS bool) tarWhiteoutConverter {
|
|
| 6 |
- return nil |
|
| 5 |
+func getWhiteoutConverter(format WhiteoutFormat, inUserNS bool) (tarWhiteoutConverter, error) {
|
|
| 6 |
+ return nil, nil |
|
| 7 | 7 |
} |