Re: [RFC 1/1] shiftfs: uid/gid shifting bind mount

From: Vivek Goyal
Date: Tue Feb 14 2017 - 18:03:20 EST

On Sun, Feb 05, 2017 at 05:18:11PM -0800, James Bottomley wrote:

> > shiftfs is going to miss out on overlayfs bug fixes related to user
> > credentials differ from mounter credentials, like fd3220d ("ovl:
> > update S_ISGID when setting posix ACLs"). I am not sure that this
> > specific case is relevant to shiftfs, but there could be other.
> OK, so shiftfs doesn't have this bug and the reason why is
> illustrative: basically shiftfs does three things
> 1. lookups via a uid/gid shifted dentry cache
> 2. shifted credential inode operations permission checks on the
> underlying filesystem
> 3. location marking for unprivileged mount
> I think we've already seen that 1. isn't from overlayfs but the
> functionality could be added to overlayfs, I suppose. The big problem
> is 2. The overlayfs code emulates the permission checks, which makes
> it rather complex (this is where you get your bugs like the above
> from). I did actually look at adding 2. to overlayfs on the theory
> that a single layer overlay might be closest to what this is, but
> eventually concluded I'd have to take the special cases and add a whole
> lot more to them ... it really would increase the maintenance burden
> substantially and make the code an unreadable rats nest.

Hi James,

If we merge this functionality in overlayfs, then we could avoid extra
copy of dentry/inode and that might be a significant advantage.

W.r.t permission checks, I am wondering will it make sense to do what
overlayfs is doing for shiftfs. That is permission is checked on
two inodes. We use creds of task for checking permission on
shiftfs/overlay inode and mounter's creds on real inode.

Given we have already shifted the uid/gid for shiftfs inode, I am
wondering that why can't we simply call generic_permission(shiftfs_inode,
mask) directly in the context of caller. Something like..

shiftfs_permission() {
err = generic_permission(inode, mask);
if (err)
return err;

err = inode_permission(reali, mask);

return err;