Thread (6 messages) 6 messages, 4 authors, 2021-01-15

Re: XFS: Assertion failed

From: Eric Sandeen <hidden>
Date: 2021-01-14 19:34:25


On 1/14/21 12:24 PM, Brian Foster wrote:
On Thu, Jan 14, 2021 at 12:29:28PM -0500, Brian Foster wrote:
quoted
On Thu, Jan 14, 2021 at 05:20:29AM -0500, Yumei Huang wrote:
quoted
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..
The reproducer seems to boil down to this:

touch <file>
setfattr -n security.capability -v 0sAAAAA2IXAAAIAAAAAgAAAP////8A7gAA <file>
xfs_io -c "open -t <file>"

... and afaict, the behavior is as expected. do_truncate() sets
ATTR_KILL_PRIV via dentry_needs_remove_privs() and calls into
notify_change(). That eventually gets to xfs_vn_setattr_size(), which
calls xfs_vn_change_ok() -> setattr_prepare(). setattr_prepare() handles
ATTR_KILL_PRIV (which remains set in ->ia_valid), and then we return,
fall into xfs_setattr_size() and that triggers the assert failure. ISTM
we should probably just drop ATTR_KILL_PRIV from the assert.
I dumped the ia_valid value, and it's got these bits set:

3       ATTR_SIZE
5       ATTR_MTIME
6       ATTR_CTIME
9       ATTR_FORCE
13      ATTR_FILE
14      ATTR_KILL_PRIV
15      ATTR_OPEN

so you are right about ATTR_KILL_PRIV

It's been in the assert forever, though, which is interesting?

-Eric
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help