whiterose

linux unikernel
Log | Files | Refs | README | LICENSE | git clone https://git.ne02ptzero.me/git/whiterose

commit e6333d72cb373239400969f5d10204c094a9712a
parent 70f4828201e3bc9a5ac52d1f7ede06e56194268a
Author: Linus Torvalds <torvalds@linux-foundation.org>
Date:   Wed, 12 Dec 2018 18:19:44 -0800

Merge tag 'ovl-fixes-4.20-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs

Pull overlayfs fixes from Miklos Szeredi:
 "Needed to revert a patch, because it possibly introduces a security
  hole. Since the patch is basically a conceptual cleanup, not a bug
  fix, it's safe to revert. I'm not giving up on this, and discussions
  seemed to have reached an agreement over how to move forward, but that
  can wait 'till the next release.

  The other two patches are fixes for bugs introduced in recent
  releases"

* tag 'ovl-fixes-4.20-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs:
  Revert "ovl: relax permission checking on underlying layers"
  ovl: fix decode of dir file handle with multi lower layers
  ovl: fix missing override creds in link of a metacopy upper

Diffstat:
Mfs/overlayfs/dir.c | 14+++++++++++++-
Mfs/overlayfs/export.c | 6+++---
Mfs/overlayfs/inode.c | 17++++-------------
3 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c @@ -651,6 +651,18 @@ static int ovl_symlink(struct inode *dir, struct dentry *dentry, return ovl_create_object(dentry, S_IFLNK, 0, link); } +static int ovl_set_link_redirect(struct dentry *dentry) +{ + const struct cred *old_cred; + int err; + + old_cred = ovl_override_creds(dentry->d_sb); + err = ovl_set_redirect(dentry, false); + revert_creds(old_cred); + + return err; +} + static int ovl_link(struct dentry *old, struct inode *newdir, struct dentry *new) { @@ -670,7 +682,7 @@ static int ovl_link(struct dentry *old, struct inode *newdir, goto out_drop_write; if (ovl_is_metacopy_dentry(old)) { - err = ovl_set_redirect(old, false); + err = ovl_set_link_redirect(old); if (err) goto out_drop_write; } diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c @@ -754,9 +754,8 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb, goto out; } - /* Otherwise, get a connected non-upper dir or disconnected non-dir */ - if (d_is_dir(origin.dentry) && - (origin.dentry->d_flags & DCACHE_DISCONNECTED)) { + /* Find origin.dentry again with ovl_acceptable() layer check */ + if (d_is_dir(origin.dentry)) { dput(origin.dentry); origin.dentry = NULL; err = ovl_check_origin_fh(ofs, fh, true, NULL, &stack); @@ -769,6 +768,7 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb, goto out_err; } + /* Get a connected non-upper dir or disconnected non-dir */ dentry = ovl_get_dentry(sb, NULL, &origin, index); out: diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c @@ -286,22 +286,13 @@ int ovl_permission(struct inode *inode, int mask) if (err) return err; - /* No need to do any access on underlying for special files */ - if (special_file(realinode->i_mode)) - return 0; - - /* No need to access underlying for execute */ - mask &= ~MAY_EXEC; - if ((mask & (MAY_READ | MAY_WRITE)) == 0) - return 0; - - /* Lower files get copied up, so turn write access into read */ - if (!upperinode && mask & MAY_WRITE) { + old_cred = ovl_override_creds(inode->i_sb); + if (!upperinode && + !special_file(realinode->i_mode) && mask & MAY_WRITE) { mask &= ~(MAY_WRITE | MAY_APPEND); + /* Make sure mounter can read file for copy up later */ mask |= MAY_READ; } - - old_cred = ovl_override_creds(inode->i_sb); err = inode_permission(realinode, mask); revert_creds(old_cred);