Skip to content

Commit b32687d

Browse files
committed
bugfix: sort mounts according to the depth of destination path
Signed-off-by: YaoZengzeng <[email protected]>
1 parent ff5d11f commit b32687d

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

daemon/mgr/spec_mount.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"context"
55
"fmt"
66
"os"
7+
"path/filepath"
8+
"sort"
79
"strconv"
810

911
"github.com/alibaba/pouch/apis/types"
@@ -108,7 +110,7 @@ func setupMounts(ctx context.Context, c *Container, s *specs.Spec) error {
108110
mounts = append(mounts, generateNetworkMounts(c)...)
109111
}
110112

111-
s.Mounts = mounts
113+
s.Mounts = sortMounts(mounts)
112114

113115
if c.HostConfig.Privileged {
114116
if !s.Root.Readonly {
@@ -175,3 +177,30 @@ func trySetupNetworkMount(mount *types.MountPoint, c *Container) bool {
175177

176178
return false
177179
}
180+
181+
// mounts defines how to sort specs.Mount.
182+
type mounts []specs.Mount
183+
184+
// Len returns the number of mounts.
185+
func (m mounts) Len() int {
186+
return len(m)
187+
}
188+
189+
// Less returns true if the destination of mount i < destination of mount j
190+
// in lexicographic order.
191+
func (m mounts) Less(i, j int) bool {
192+
return filepath.Clean(m[i].Destination) < filepath.Clean(m[j].Destination)
193+
}
194+
195+
// Swap swaps two items in an array of mounts.
196+
func (m mounts) Swap(i, j int) {
197+
m[i], m[j] = m[j], m[i]
198+
}
199+
200+
// sortMounts sorts an array of mounts in lexicographic order. This ensure that
201+
// the mount like /etc/resolv.conf will not mount before /etc, so /etc will
202+
// not shadow /etc/resolv.conf
203+
func sortMounts(m []specs.Mount) []specs.Mount {
204+
sort.Stable(mounts(m))
205+
return m
206+
}

daemon/mgr/spec_mount_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package mgr
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
7+
specs "github.com/opencontainers/runtime-spec/specs-go"
8+
)
9+
10+
func Test_sortMounts(t *testing.T) {
11+
tests := []struct {
12+
name string
13+
args []specs.Mount
14+
want []specs.Mount
15+
}{
16+
{
17+
"Mounts is nil case",
18+
nil,
19+
nil,
20+
},
21+
{
22+
"Normal Mounts",
23+
[]specs.Mount{
24+
{Destination: "/etc/resolv.conf"},
25+
{Destination: "/etc"},
26+
},
27+
[]specs.Mount{
28+
{Destination: "/etc"},
29+
{Destination: "/etc/resolv.conf"},
30+
},
31+
},
32+
}
33+
for _, tt := range tests {
34+
t.Run(tt.name, func(t *testing.T) {
35+
got := sortMounts(tt.args)
36+
if !reflect.DeepEqual(got, tt.want) {
37+
t.Errorf("sortMounts() = %v, want %v", got, tt.want)
38+
}
39+
})
40+
}
41+
}

0 commit comments

Comments
 (0)