Lower layer files that can not be copied up are not writable.

Make access(W_OK) return EACCES in overlayfs if file exists only
on lower layer and can not be copied up. Earlier, access(W_OK)
was succeeding but operations that cause copy-up (like
open(WR_ONLY)) were failing. This is likely to confuse
applications.

PiperOrigin-RevId: 465818314
This commit is contained in:
Ayush Ranjan
2022-08-06 20:01:51 -07:00
committed by gVisor bot
parent 919910ce67
commit 0d7a1d0711
2 changed files with 24 additions and 7 deletions
+14 -6
View File
@@ -31,6 +31,18 @@ func (d *dentry) isCopiedUp() bool {
return d.copiedUp.Load() != 0
}
func (d *dentry) canBeCopiedUp() bool {
ftype := d.mode.Load() & linux.S_IFMT
switch ftype {
case linux.S_IFREG, linux.S_IFDIR, linux.S_IFLNK, linux.S_IFBLK, linux.S_IFCHR:
// Can be copied-up.
return true
default:
// Can't be copied-up.
return false
}
}
// copyUpLocked ensures that d exists on the upper layer, i.e. d.upperVD.Ok().
//
// Preconditions: filesystem.renameMu must be locked.
@@ -48,12 +60,7 @@ func (d *dentry) copyUpMaybeSyntheticMountpointLocked(ctx context.Context, forSy
// credentials from context rather an take an explicit creds parameter.
ctx = auth.ContextWithCredentials(ctx, d.fs.creds)
ftype := d.mode.Load() & linux.S_IFMT
switch ftype {
case linux.S_IFREG, linux.S_IFDIR, linux.S_IFLNK, linux.S_IFBLK, linux.S_IFCHR:
// Can be copied-up.
default:
// Can't be copied-up.
if !d.canBeCopiedUp() {
return linuxerr.EPERM
}
@@ -92,6 +99,7 @@ func (d *dentry) copyUpMaybeSyntheticMountpointLocked(ctx context.Context, forSy
}
// Perform copy-up.
ftype := d.mode.Load() & linux.S_IFMT
newpop := vfs.PathOperation{
Root: d.parent.upperVD,
Start: d.parent.upperVD,
+10 -1
View File
@@ -585,9 +585,18 @@ func (fs *filesystem) AccessAt(ctx context.Context, rp *vfs.ResolvingPath, creds
if err := d.checkPermissions(creds, ats); err != nil {
return err
}
if ats.MayWrite() && rp.Mount().ReadOnly() {
if !ats.MayWrite() {
// Not requesting write permission. Allow it.
return nil
}
if rp.Mount().ReadOnly() {
return linuxerr.EROFS
}
if !d.upperVD.Ok() && !d.canBeCopiedUp() {
// A lower layer file that can not be copied up, can not be written to.
// Error out here. Don't give the application false hopes.
return linuxerr.EACCES
}
return nil
}