Skip to content
This repository was archived by the owner on Mar 27, 2024. It is now read-only.

Commit a2c8cc9

Browse files
author
Priya Wadhwa
committed
Extract symlinks to filesystem and add support for a whitelist
1 parent e57f9f2 commit a2c8cc9

File tree

7 files changed

+65
-26
lines changed

7 files changed

+65
-26
lines changed

pkg/util/cloud_prepper.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func (p CloudPrepper) GetFileSystem() (string, error) {
5959
return "", err
6060
}
6161

62-
return path, getFileSystemFromReference(ref, p.ImageSource, path)
62+
return path, GetFileSystemFromReference(ref, p.ImageSource, path, []string{})
6363
}
6464

6565
func (p CloudPrepper) GetConfig() (ConfigSchema, error) {

pkg/util/daemon_prepper.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func (p DaemonPrepper) GetFileSystem() (string, error) {
6464
if err != nil {
6565
return "", err
6666
}
67-
return path, getFileSystemFromReference(ref, src, path)
67+
return path, GetFileSystemFromReference(ref, src, path, []string{})
6868
}
6969

7070
func (p DaemonPrepper) GetConfig() (ConfigSchema, error) {

pkg/util/docker_utils.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ func unpackDockerSave(tarPath string, target string) error {
115115
}
116116

117117
for _, layer := range layers {
118-
if err = UnTar(bytes.NewReader(layerMap[layer]), target); err != nil {
118+
if err = UnTar(bytes.NewReader(layerMap[layer]), target, []string{}); err != nil {
119119
return fmt.Errorf("Could not unpack layer %s: %s", layer, err)
120120
}
121121
}

pkg/util/image_prep_utils.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ func getImageFromTar(tarPath string) (string, error) {
127127
return tempPath, unpackDockerSave(tarPath, tempPath)
128128
}
129129

130-
func getFileSystemFromReference(ref types.ImageReference, imgSrc types.ImageSource, path string) error {
130+
func GetFileSystemFromReference(ref types.ImageReference, imgSrc types.ImageSource, path string, whitelist []string) error {
131131
img, err := ref.NewImage(nil)
132132
if err != nil {
133133
return err
@@ -151,7 +151,7 @@ func getFileSystemFromReference(ref types.ImageReference, imgSrc types.ImageSour
151151
}
152152
}
153153
tr := tar.NewReader(reader)
154-
if err := unpackTar(tr, path); err != nil {
154+
if err := unpackTar(tr, path, whitelist); err != nil {
155155
return err
156156
}
157157
}

pkg/util/tar_prepper.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,12 @@ package util
1919
import (
2020
"encoding/json"
2121
"errors"
22-
"io/ioutil"
23-
"os"
24-
"path/filepath"
25-
2622
"github.com/containers/image/docker/tarfile"
2723
"github.com/docker/docker/client"
2824
"github.com/sirupsen/logrus"
25+
"io/ioutil"
26+
"os"
27+
"path/filepath"
2928
)
3029

3130
type TarPrepper struct {
@@ -62,7 +61,7 @@ func (p TarPrepper) GetConfig() (ConfigSchema, error) {
6261
return ConfigSchema{}, err
6362
}
6463
defer f.Close()
65-
if err := UnTar(f, tempDir); err != nil {
64+
if err := UnTar(f, tempDir, []string{}); err != nil {
6665
return ConfigSchema{}, err
6766
}
6867

pkg/util/tar_utils.go

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626
"github.com/sirupsen/logrus"
2727
)
2828

29-
func unpackTar(tr *tar.Reader, path string) error {
29+
func unpackTar(tr *tar.Reader, path string, whitelist []string) error {
3030
for {
3131
header, err := tr.Next()
3232
if err == io.EOF {
@@ -37,7 +37,6 @@ func unpackTar(tr *tar.Reader, path string) error {
3737
logrus.Error("Error getting next tar header")
3838
return err
3939
}
40-
4140
if strings.Contains(header.Name, ".wh.") {
4241
rmPath := filepath.Join(path, header.Name)
4342
// Remove the .wh file if it was extracted.
@@ -49,13 +48,16 @@ func unpackTar(tr *tar.Reader, path string) error {
4948

5049
// Remove the whited-out path.
5150
newName := strings.Replace(rmPath, ".wh.", "", 1)
52-
if err = os.RemoveAll(newName); err != nil {
51+
if err = walkAndRemove(newName); err != nil {
5352
logrus.Error(err)
5453
}
5554
continue
5655
}
57-
5856
target := filepath.Join(path, header.Name)
57+
// Make sure the target isn't part of the whitelist
58+
if checkWhitelist(target, whitelist) {
59+
continue
60+
}
5961
mode := header.FileInfo().Mode()
6062
switch header.Typeflag {
6163

@@ -65,7 +67,7 @@ func unpackTar(tr *tar.Reader, path string) error {
6567
if err := os.MkdirAll(target, mode); err != nil {
6668
return err
6769
}
68-
} else {
70+
// In some cases, MkdirAll doesn't change the permissions, so run Chmod
6971
if err := os.Chmod(target, mode); err != nil {
7072
return err
7173
}
@@ -81,7 +83,6 @@ func unpackTar(tr *tar.Reader, path string) error {
8183
return err
8284
}
8385
}
84-
8586
// It's possible we end up creating files that can't be overwritten based on their permissions.
8687
// Explicitly delete an existing file before continuing.
8788
if _, err := os.Stat(target); !os.IsNotExist(err) {
@@ -106,21 +107,52 @@ func unpackTar(tr *tar.Reader, path string) error {
106107
return err
107108
}
108109
currFile.Close()
109-
}
110+
case tar.TypeSymlink:
111+
// It's possible we end up creating files that can't be overwritten based on their permissions.
112+
// Explicitly delete an existing file before continuing.
113+
if _, err := os.Stat(target); !os.IsNotExist(err) {
114+
logrus.Debugf("Removing %s to create symlink.", target)
115+
if err := walkAndRemove(target); err != nil {
116+
logrus.Debugf("Unable to remove %s: %s", target, err)
117+
}
118+
}
110119

120+
if err = os.Symlink(header.Linkname, target); err != nil {
121+
logrus.Errorf("Failed to create symlink between %s and %s: %s", header.Linkname, target, err)
122+
}
123+
}
111124
}
112125
return nil
113126
}
114127

128+
func walkAndRemove(p string) error {
129+
return filepath.Walk(p, func(path string, info os.FileInfo, err error) error {
130+
if e := os.Chmod(path, 0777); e != nil {
131+
logrus.Errorf("Error updating file permissions on %s before removing for symlink creation", path)
132+
return e
133+
}
134+
return os.RemoveAll(path)
135+
})
136+
}
137+
138+
func checkWhitelist(target string, whitelist []string) bool {
139+
for _, w := range whitelist {
140+
if strings.HasPrefix(target, w) {
141+
return true
142+
}
143+
}
144+
return false
145+
}
146+
115147
// UnTar takes in a path to a tar file and writes the untarred version to the provided target.
116148
// Only untars one level, does not untar nested tars.
117-
func UnTar(r io.Reader, target string) error {
149+
func UnTar(r io.Reader, target string, whitelist []string) error {
118150
if _, ok := os.Stat(target); ok != nil {
119151
os.MkdirAll(target, 0775)
120152
}
121153

122154
tr := tar.NewReader(r)
123-
if err := unpackTar(tr, target); err != nil {
155+
if err := unpackTar(tr, target, whitelist); err != nil {
124156
return err
125157
}
126158
return nil

util/tar_utils_test.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,13 @@ import (
3030

3131
func TestUnTar(t *testing.T) {
3232
testCases := []struct {
33-
descrip string
34-
tarPath string
35-
target string
36-
expected string
37-
starter string
38-
err bool
33+
descrip string
34+
tarPath string
35+
target string
36+
expected string
37+
starter string
38+
whitelist []string
39+
err bool
3940
}{
4041
{
4142
descrip: "Tar with files",
@@ -76,6 +77,13 @@ func TestUnTar(t *testing.T) {
7677
expected: "testTars/la-croix-dir-update-actual",
7778
starter: "testTars/la-croix-starter",
7879
},
80+
{
81+
descrip: "Tar with whitelist",
82+
tarPath: "testTars/la-croix2.tar",
83+
target: "testTars/la-croix-whitelist",
84+
expected: "testTars/la-croix1-actual",
85+
whitelist: []string{"testTars/la-croix-whitelist/nest"},
86+
},
7987
}
8088
for _, test := range testCases {
8189
remove := true
@@ -86,7 +94,7 @@ func TestUnTar(t *testing.T) {
8694
if err != nil {
8795
t.Errorf("Error opening tar: %s", err)
8896
}
89-
if err := pkgutil.UnTar(r, test.target); err != nil && !test.err {
97+
if err := pkgutil.UnTar(r, test.target, test.whitelist); err != nil && !test.err {
9098
t.Errorf(test.descrip, "Got unexpected error: %s", err)
9199
remove = false
92100
}

0 commit comments

Comments
 (0)