Skip to content

Commit

Permalink
chown: use Link instead of Chown for dup inodes
Browse files Browse the repository at this point in the history
If the inode was already encountered and chowned, use link(2) instead
of chown(2).

This is needed when the underlying storage (as it could be overlay
with index=off) breaks the hard link on copy up.

containers#1144 added the initial
check.

Closes: containers#1257

Signed-off-by: Giuseppe Scrivano <[email protected]>
  • Loading branch information
giuseppe committed Jun 14, 2022
1 parent 8951d01 commit a7ca09e
Showing 1 changed file with 24 additions and 6 deletions.
30 changes: 24 additions & 6 deletions drivers/chown_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ type inode struct {

type platformChowner struct {
mutex sync.Mutex
inodes map[inode]bool
inodes map[inode]string
}

func newLChowner() *platformChowner {
return &platformChowner{
inodes: make(map[inode]bool),
inodes: make(map[inode]string),
}
}

Expand All @@ -40,15 +40,33 @@ func (c *platformChowner) LChown(path string, info os.FileInfo, toHost, toContai
Dev: uint64(st.Dev),
Ino: uint64(st.Ino),
}

c.mutex.Lock()
_, found := c.inodes[i]

oldTarget, found := c.inodes[i]
if !found {
c.inodes[i] = true
c.inodes[i] = path
}

// If we are dealing with a file with multiple links then keep the lock until the file is
// chowned to avoid a race where we link to the old version if the file is copied up.
if found || st.Nlink > 1 {
defer c.mutex.Unlock()
} else {
c.mutex.Unlock()
}
c.mutex.Unlock()

if found {
return nil
// If the dev/inode was already chowned then create a link to the old target instead
// of chowning it again. This is necessary when the underlying file system breaks
// inodes on copy-up (as it is with overlay with index=off) to maintain the original
// link and correct file ownership.

// The target already exists so remove it before creating the link to the new target.
if err := os.Remove(path); err != nil {
return err
}
return os.Link(oldTarget, path)
}

// Map an on-disk UID/GID pair from host to container
Expand Down

0 comments on commit a7ca09e

Please sign in to comment.