Skip to content

Commit 360c002

Browse files
committed
store: use canonical image mapping when mounting
Ensure that a mapped layer with the canonical mapping is created if one doesn't already exist. Previously, any layer was used regardless of its mapping, which resulted in the mounted image having incorrect file ownership, depending on what mapping was found. Signed-off-by: Giuseppe Scrivano <[email protected]>
1 parent 7082298 commit 360c002

File tree

2 files changed

+107
-37
lines changed

2 files changed

+107
-37
lines changed

store.go

+96-36
Original file line numberDiff line numberDiff line change
@@ -2830,7 +2830,11 @@ func (s *store) Version() ([][2]string, error) {
28302830
return [][2]string{}, nil
28312831
}
28322832

2833-
func (s *store) mount(id string, options drivers.MountOpts) (string, error) {
2833+
func (s *store) MountImage(id string, mountOpts []string, mountLabel string) (string, error) {
2834+
if err := validateMountOptions(mountOpts); err != nil {
2835+
return "", err
2836+
}
2837+
28342838
// We need to make sure the home mount is present when the Mount is done, which happens by possibly reinitializing the graph driver
28352839
// in startUsingGraphDriver().
28362840
if err := s.startUsingGraphDriver(); err != nil {
@@ -2842,57 +2846,61 @@ func (s *store) mount(id string, options drivers.MountOpts) (string, error) {
28422846
if err != nil {
28432847
return "", err
28442848
}
2845-
if options.UidMaps != nil || options.GidMaps != nil {
2846-
options.DisableShifting = !s.canUseShifting(options.UidMaps, options.GidMaps)
2847-
}
2849+
var imageHomeStore roImageStore
28482850

2849-
// function used to have a scope for rlstore.StopWriting()
2850-
tryMount := func() (string, error) {
2851-
if err := rlstore.startWriting(); err != nil {
2851+
if err := rlstore.startWriting(); err != nil {
2852+
return "", err
2853+
}
2854+
defer rlstore.stopWriting()
2855+
for _, s := range lstores {
2856+
if err := s.startReading(); err != nil {
28522857
return "", err
28532858
}
2854-
defer rlstore.stopWriting()
2855-
if rlstore.Exists(id) {
2856-
return rlstore.Mount(id, options)
2857-
}
2858-
return "", nil
2859+
defer s.stopReading()
28592860
}
2860-
mountPoint, err := tryMount()
2861-
if mountPoint != "" || err != nil {
2862-
return mountPoint, err
2861+
if err := s.imageStore.startWriting(); err != nil {
2862+
return "", err
28632863
}
2864+
defer s.imageStore.stopWriting()
28642865

2865-
// check if the layer is in a read-only store, and return a better error message
2866-
for _, store := range lstores {
2867-
if err := store.startReading(); err != nil {
2868-
return "", err
2869-
}
2870-
exists := store.Exists(id)
2871-
store.stopReading()
2872-
if exists {
2873-
return "", fmt.Errorf("mounting read/only store images is not allowed: %w", ErrStoreIsReadOnly)
2866+
cimage, err := s.imageStore.Get(id)
2867+
if err == nil {
2868+
imageHomeStore = s.imageStore
2869+
} else {
2870+
for _, s := range s.roImageStores {
2871+
if err := s.startReading(); err != nil {
2872+
return "", err
2873+
}
2874+
defer s.stopReading()
2875+
cimage, err = s.Get(id)
2876+
if err == nil {
2877+
imageHomeStore = s
2878+
break
2879+
}
28742880
}
28752881
}
2882+
if cimage == nil {
2883+
return "", fmt.Errorf("locating image with ID %q: %w", id, ErrImageUnknown)
2884+
}
28762885

2877-
return "", ErrLayerUnknown
2878-
}
2879-
2880-
func (s *store) MountImage(id string, mountOpts []string, mountLabel string) (string, error) {
2881-
// Append ReadOnly option to mountOptions
2882-
img, err := s.Image(id)
2886+
idmappingsOpts := types.IDMappingOptions{
2887+
HostUIDMapping: true,
2888+
HostGIDMapping: true,
2889+
}
2890+
ilayer, err := s.imageTopLayerForMapping(cimage, imageHomeStore, rlstore, lstores, idmappingsOpts)
28832891
if err != nil {
28842892
return "", err
28852893
}
28862894

2887-
if err := validateMountOptions(mountOpts); err != nil {
2888-
return "", err
2895+
if len(ilayer.UIDMap) > 0 || len(ilayer.GIDMap) > 0 {
2896+
return "", fmt.Errorf("cannot create an image with canonical UID/GID mappings in a read-only store")
28892897
}
2898+
28902899
options := drivers.MountOpts{
28912900
MountLabel: mountLabel,
28922901
Options: append(mountOpts, "ro"),
28932902
}
2894-
2895-
return s.mount(img.TopLayer, options)
2903+
return rlstore.Mount(ilayer.ID, options)
28962904
}
28972905

28982906
func (s *store) Mount(id, mountLabel string) (string, error) {
@@ -2914,7 +2922,43 @@ func (s *store) Mount(id, mountLabel string) (string, error) {
29142922
}
29152923
}
29162924
}
2917-
return s.mount(id, options)
2925+
2926+
// We need to make sure the home mount is present when the Mount is done, which happens by possibly reinitializing the graph driver
2927+
// in startUsingGraphDriver().
2928+
if err := s.startUsingGraphDriver(); err != nil {
2929+
return "", err
2930+
}
2931+
defer s.stopUsingGraphDriver()
2932+
2933+
rlstore, lstores, err := s.bothLayerStoreKindsLocked()
2934+
if err != nil {
2935+
return "", err
2936+
}
2937+
if options.UidMaps != nil || options.GidMaps != nil {
2938+
options.DisableShifting = !s.canUseShifting(options.UidMaps, options.GidMaps)
2939+
}
2940+
2941+
if err := rlstore.startWriting(); err != nil {
2942+
return "", err
2943+
}
2944+
defer rlstore.stopWriting()
2945+
if rlstore.Exists(id) {
2946+
return rlstore.Mount(id, options)
2947+
}
2948+
2949+
// check if the layer is in a read-only store, and return a better error message
2950+
for _, store := range lstores {
2951+
if err := store.startReading(); err != nil {
2952+
return "", err
2953+
}
2954+
exists := store.Exists(id)
2955+
store.stopReading()
2956+
if exists {
2957+
return "", fmt.Errorf("mounting read/only store images is not allowed: %w", ErrStoreIsReadOnly)
2958+
}
2959+
}
2960+
2961+
return "", ErrLayerUnknown
29182962
}
29192963

29202964
func (s *store) Mounted(id string) (int, error) {
@@ -2938,7 +2982,23 @@ func (s *store) UnmountImage(id string, force bool) (bool, error) {
29382982
if err != nil {
29392983
return false, err
29402984
}
2941-
return s.Unmount(img.TopLayer, force)
2985+
2986+
return writeToLayerStore(s, func(lstore rwLayerStore) (bool, error) {
2987+
for _, layerID := range img.MappedTopLayers {
2988+
l, err := lstore.Get(layerID)
2989+
if err != nil {
2990+
if err == ErrLayerUnknown {
2991+
continue
2992+
}
2993+
return false, err
2994+
}
2995+
// check if the layer with the canonical mapping is in the mapped top layers
2996+
if len(l.UIDMap) == 0 && len(l.GIDMap) == 0 {
2997+
return lstore.unmount(l.ID, force, false)
2998+
}
2999+
}
3000+
return lstore.unmount(img.TopLayer, force, false)
3001+
})
29423002
}
29433003

29443004
func (s *store) Unmount(id string, force bool) (bool, error) {

tests/idmaps.bats

+11-1
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,17 @@ load helpers
290290
done
291291
# Create new containers based on the layer.
292292
imagename=idmappedimage
293-
storage create-image --name=$imagename $lowerlayer
293+
run storage create-image --name=$imagename $lowerlayer
294+
[ "$status" -eq 0 ]
295+
296+
run storage --debug=false mount -r $imagename
297+
[ "$status" -eq 0 ]
298+
mountpoint="$output"
299+
run stat -c %u:%g $mountpoint/file1
300+
# make sure the file shows the correct ownership after the image is mounted
301+
[ "$output" == "0:0" ]
302+
run storage umount $imagename
303+
[ "$status" -eq 0 ]
294304

295305
run storage --debug=false create-container --hostuidmap --hostgidmap $imagename
296306
[ "$status" -eq 0 ]

0 commit comments

Comments
 (0)