Skip to content

Commit 9dc8415

Browse files
Gao Xianggregkh
Gao Xiang
authored andcommitted
staging: erofs: fix fast symlink w/o xattr when fs xattr is on
commit 7077fff upstream. Currently, this will hit a BUG_ON for these symlinks as follows: - kernel message ------------[ cut here ]------------ kernel BUG at drivers/staging/erofs/xattr.c:59! SMP PTI CPU: 1 PID: 1170 Comm: getllxattr Not tainted 4.20.0-rc6+ #92 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-2.fc27 04/01/2014 RIP: 0010:init_inode_xattrs+0x22b/0x270 Code: 48 0f 45 ea f0 ff 4d 34 74 0d 41 83 4c 24 e0 01 31 c0 e9 00 fe ff ff 48 89 ef e8 e0 31 9e ff eb e9 89 e8 e9 ef fd ff ff 0f 0$ <0f> 0b 48 89 ef e8 fb f6 9c ff 48 8b 45 08 a8 01 75 24 f0 ff 4d 34 RSP: 0018:ffffa03ac026bdf8 EFLAGS: 00010246 ------------[ cut here ]------------ ... Call Trace: erofs_listxattr+0x30/0x2c0 ? selinux_inode_listxattr+0x5a/0x80 ? kmem_cache_alloc+0x33/0x170 ? security_inode_listxattr+0x27/0x40 listxattr+0xaf/0xc0 path_listxattr+0x5a/0xa0 do_syscall_64+0x43/0xf0 entry_SYSCALL_64_after_hwframe+0x44/0xa9 ... ---[ end trace 3c24b49408dc0c72 ]--- Fix it by checking ->xattr_isize in init_inode_xattrs(), and it also fixes improper return value -ENOTSUPP (it should be -ENODATA if xattr is enabled) for those inodes. Fixes: b17500a ("staging: erofs: introduce xattr & acl support") Cc: <[email protected]> # 4.19+ Reported-by: Li Guifu <[email protected]> Tested-by: Li Guifu <[email protected]> Reviewed-by: Chao Yu <[email protected]> Signed-off-by: Gao Xiang <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent f581642 commit 9dc8415

File tree

2 files changed

+24
-9
lines changed

2 files changed

+24
-9
lines changed

drivers/staging/erofs/inode.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,16 +184,16 @@ static int fill_inode(struct inode *inode, int isdir)
184184
/* setup the new inode */
185185
if (S_ISREG(inode->i_mode)) {
186186
#ifdef CONFIG_EROFS_FS_XATTR
187-
if (vi->xattr_isize)
188-
inode->i_op = &erofs_generic_xattr_iops;
187+
inode->i_op = &erofs_generic_xattr_iops;
189188
#endif
190189
inode->i_fop = &generic_ro_fops;
191190
} else if (S_ISDIR(inode->i_mode)) {
192191
inode->i_op =
193192
#ifdef CONFIG_EROFS_FS_XATTR
194-
vi->xattr_isize ? &erofs_dir_xattr_iops :
195-
#endif
193+
&erofs_dir_xattr_iops;
194+
#else
196195
&erofs_dir_iops;
196+
#endif
197197
inode->i_fop = &erofs_dir_fops;
198198
} else if (S_ISLNK(inode->i_mode)) {
199199
/* by default, page_get_link is used for symlink */

drivers/staging/erofs/xattr.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,26 @@ static int init_inode_xattrs(struct inode *inode)
5555
return 0;
5656

5757
vi = EROFS_V(inode);
58-
BUG_ON(!vi->xattr_isize);
58+
59+
/*
60+
* bypass all xattr operations if ->xattr_isize is not greater than
61+
* sizeof(struct erofs_xattr_ibody_header), in detail:
62+
* 1) it is not enough to contain erofs_xattr_ibody_header then
63+
* ->xattr_isize should be 0 (it means no xattr);
64+
* 2) it is just to contain erofs_xattr_ibody_header, which is on-disk
65+
* undefined right now (maybe use later with some new sb feature).
66+
*/
67+
if (vi->xattr_isize == sizeof(struct erofs_xattr_ibody_header)) {
68+
errln("xattr_isize %d of nid %llu is not supported yet",
69+
vi->xattr_isize, vi->nid);
70+
return -ENOTSUPP;
71+
} else if (vi->xattr_isize < sizeof(struct erofs_xattr_ibody_header)) {
72+
if (unlikely(vi->xattr_isize)) {
73+
DBG_BUGON(1);
74+
return -EIO; /* xattr ondisk layout error */
75+
}
76+
return -ENOATTR;
77+
}
5978

6079
sbi = EROFS_I_SB(inode);
6180
it.blkaddr = erofs_blknr(iloc(sbi, vi->nid) + vi->inode_isize);
@@ -414,7 +433,6 @@ static int erofs_xattr_generic_get(const struct xattr_handler *handler,
414433
struct dentry *unused, struct inode *inode,
415434
const char *name, void *buffer, size_t size)
416435
{
417-
struct erofs_vnode *const vi = EROFS_V(inode);
418436
struct erofs_sb_info *const sbi = EROFS_I_SB(inode);
419437

420438
switch (handler->flags) {
@@ -432,9 +450,6 @@ static int erofs_xattr_generic_get(const struct xattr_handler *handler,
432450
return -EINVAL;
433451
}
434452

435-
if (!vi->xattr_isize)
436-
return -ENOATTR;
437-
438453
return erofs_getxattr(inode, handler->flags, name, buffer, size);
439454
}
440455

0 commit comments

Comments
 (0)