From: Yumei Huang <yuhuang@redhat.com>
To: Dave Chinner <david@fromorbit.com>
Cc: Brian Foster <bfoster@redhat.com>, linux-xfs@vger.kernel.org
Subject: Re: XFS: Assertion failed
Date: Fri, 15 Jan 2021 03:36:40 -0500 (EST) [thread overview]
Message-ID: <1914065699.64814368.1610699800882.JavaMail.zimbra@redhat.com> (raw)
In-Reply-To: <20210114212102.GM331610@dread.disaster.area>
----- Original Message -----
> From: "Dave Chinner" <david@fromorbit.com>
> To: "Brian Foster" <bfoster@redhat.com>
> Cc: "Yumei Huang" <yuhuang@redhat.com>, linux-xfs@vger.kernel.org
> Sent: Friday, January 15, 2021 5:21:02 AM
> Subject: Re: XFS: Assertion failed
>
> On Thu, Jan 14, 2021 at 12:29:28PM -0500, Brian Foster wrote:
> > On Thu, Jan 14, 2021 at 05:20:29AM -0500, Yumei Huang wrote:
> > > Hit the issue when doing syzkaller test with kernel 5.11.0-rc3(65f0d241).
> > > The C reproducer is attached.
> > >
> > > Steps to Reproduce:
> > > 1. # gcc -pthread -o reproducer reproducer.c
> > > 2. # ./reproducer
> > >
> > >
> > > Test results:
> > > [ 131.726790] XFS: Assertion failed: (iattr->ia_valid &
> > > (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
> > > ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0, file:
> > > fs/xfs/xfs_iops.c, line: 849
> > > [ 131.743687] ------------[ cut here ]------------
> >
> > Some quick initial analysis from a run of the reproducer... It looks
> > like it calls into xfs_setattr_size() with ATTR_KILL_PRIV set in
> > ->ia_valid. This appears to originate in the VFS via handle_truncate()
> > -> do_truncate() -> dentry_needs_remove_privs().
> >
> > An strace of the reproducer shows the following calls:
> >
> > ...
> > [pid 1524] creat("./file0", 010) = 3
> > ...
> > [pid 1524] fsetxattr(3, "security.capability",
> > "\0\0\0\3b\27\0\0\10\0\0\0\2\0\0\0\377\377\377\377\0\356\0", 24, 0
> > <unfinished ...>
> > ...
> > [pid 1524] creat("./file0", 010 <unfinished ...>
> > ...
> >
> > So I'm guessing there's an attempt to open this file with O_TRUNC with
> > this particular xattr set (unexpectedly?). Indeed, after the reproducer
> > leaves file01 around with the xattr, a subsequent xfs_io -c "open -t
> > ..." attempt triggers the assert again, and then the xattr disappears.
> > I'd have to dig more into the associated vfs code to grok the expected
> > behavior and whether there's a problem here..
>
> Changing the size of the inode is is all that xfs_setattr_size()
> should be doing. Stripping capability attributes should have been
> already been done by the generic setattr code before we get to
> xfs_setattr_size(), so ATTR_KILL_PRIV should not be set at that
> point.
>
> notify_change() used to always strip ATTR_KILL_PRIV from ia_valid
> when it sets up the flags necessary to strip privileges in the
> ->setattr callout. But it doesn't appear to do so always anymore:
>
> if (ia_valid & ATTR_KILL_PRIV) {
> error = security_inode_need_killpriv(dentry);
> if (error < 0)
> return error;
> if (error == 0)
> ia_valid = attr->ia_valid &= ~ATTR_KILL_PRIV;
> }
>
> If ATTR_KILL_PRIV is still set, this implies
> security_inode_need_killpriv() returned > 0 for some reason. I'm
> assuming that this code ran:
>
> security_inode_need_killpriv()
> call_int_hook(inode_need_killpriv, 0, dentry);
>
> And the only implemented hook is this:
>
> LSM_HOOK_INIT(inode_need_killpriv, cap_inode_need_killpriv),
>
> /**
> * cap_inode_need_killpriv - Determine if inode change affects privileges
> * @dentry: The inode/dentry in being changed with change marked
> ATTR_KILL_PRIV
> *
> * Determine if an inode having a change applied that's marked ATTR_KILL_PRIV
> * affects the security markings on that inode, and if it is, should
> * inode_killpriv() be invoked or the change rejected.
> *
> * Returns 1 if security.capability has a value, meaning inode_killpriv()
> * is required, 0 otherwise, meaning inode_killpriv() is not required.
> */
> int cap_inode_need_killpriv(struct dentry *dentry)
> {
> struct inode *inode = d_backing_inode(dentry);
> int error;
>
> error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);
> return error > 0;
> }
>
> And that's the xattr that the reproducer is setting. So, smoking
> gun.
>
> we've done a lookup on the security.capability xattr which it
> found so notify_change() does not clear ATTR_KILL_PRIV. The xattr
> gets killed in setattr_prepare() but it does not clear
> ATTR_KILL_PRIV, and hence we hit the assert faili when we get into
> xfs_setattr_size.
>
> Looks like a regression introduced in 2016 by:
>
> commit 030b533c4fd4d2ec3402363323de4bb2983c9cee
> Author: Jan Kara <jack@suse.cz>
> Date: Thu May 26 17:21:32 2016 +0200
>
> fs: Avoid premature clearing of capabilities
>
> Currently, notify_change() clears capabilities or IMA attributes by
> calling security_inode_killpriv() before calling into ->setattr. Thus it
> happens before any other permission checks in inode_change_ok() and user
> is thus allowed to trigger clearing of capabilities or IMA attributes
> for any file he can look up e.g. by calling chown for that file. This is
> unexpected and can lead to user DoSing a system.
>
> Fix the problem by calling security_inode_killpriv() at the end of
> inode_change_ok() instead of from notify_change(). At that moment we are
> sure user has permissions to do the requested change.
>
> References: CVE-2015-1350
> Reviewed-by: Christoph Hellwig <hch@lst.de>
> Signed-off-by: Jan Kara <jack@suse.cz>
>
> The bug is harmless, it will only trigger the assert on debug XFS
> kernels, but otherwise ATTR_KILL_PRIV is not checked/used by
> xfs_setattr_size.
>
> Removing ATTR_KILL_PRIV from the assert is probably all that is
> needed. Can you write a patch for that, Yumei?
Sure, I will send the patch soon.
Best Regards,
Yumei Huang
>
> Cheers,
>
> Dave.
> --
> Dave Chinner
> david@fromorbit.com
>
>
prev parent reply other threads:[~2021-01-15 8:38 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <1599642077.64707510.1610619249861.JavaMail.zimbra@redhat.com>
2021-01-14 10:20 ` XFS: Assertion failed Yumei Huang
2021-01-14 17:29 ` Brian Foster
2021-01-14 18:24 ` Brian Foster
2021-01-14 19:33 ` Eric Sandeen
2021-01-14 21:21 ` Dave Chinner
2021-01-15 8:36 ` Yumei Huang [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1914065699.64814368.1610699800882.JavaMail.zimbra@redhat.com \
--to=yuhuang@redhat.com \
--cc=bfoster@redhat.com \
--cc=david@fromorbit.com \
--cc=linux-xfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox