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

From: James Bottomley
Date: Tue Feb 14 2017 - 18:46:06 EST


On Tue, 2017-02-14 at 18:03 -0500, Vivek Goyal wrote:
> 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.

I made that argument to Viro originally when I tried to do all lookups
via the underlying cache. In the end, it's 192 bytes per dentry and
584 per inode, all of which are reclaimable, so it's not much of an
advantage and it is a great simplification to the code. In general if
you have a natural separation, you should make the layers reflect it.

My container use case doesn't use overlayfs currently, so to me it
wouldn't provide any advantage whatsoever.

> 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.

The mounter's creds for overlay are usually admin ones, so it's local
permission check asks should I? and the later one asks can I? (as in
would my original admin creds allow this). In many ways, overlayfs is
ignoring the fact that the underlying ->permissions() call might have
failed for some good reason on the current creds. I don't think any
serious trouble results from this but it strikes me as icky.

> Given we have already shifted the uid/gid for shiftfs inode, I am
> wondering that why can't we simply call generic_permission(shiftfs_in
> ode, mask) directly in the context of caller. Something like..
>
> shiftfs_permission() {
> err = generic_permission(inode, mask);
> if (err)
> return err;
>
> switch_to_mounter_creds;
> err = inode_permission(reali, mask);
> revert_creds();
>
> return err;
> }

Because if the reali->d_iop->permission exists, you should use it. You
could argue shiftfs_permission should be

if (iop->permission) {
oldcred = shiftfs_new_creds(&newcred, inode->i_sb);
err = iop->permission(reali, mask);
shiftfs_old_creds(oldcred, &newcred);
} else
err = generic_permission(inode, mask);

But really that's a small optimisation.

James