]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/5.0.1/staging-erofs-fix-fast-symlink-w-o-xattr-when-fs-xattr-is-on.patch
5.0-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 5.0.1 / staging-erofs-fix-fast-symlink-w-o-xattr-when-fs-xattr-is-on.patch
1 From 7077fffcb0b0b65dc75e341306aeef4d0e7f2ec6 Mon Sep 17 00:00:00 2001
2 From: Gao Xiang <gaoxiang25@huawei.com>
3 Date: Mon, 14 Jan 2019 19:40:23 +0800
4 Subject: staging: erofs: fix fast symlink w/o xattr when fs xattr is on
5
6 From: Gao Xiang <gaoxiang25@huawei.com>
7
8 commit 7077fffcb0b0b65dc75e341306aeef4d0e7f2ec6 upstream.
9
10 Currently, this will hit a BUG_ON for these symlinks as follows:
11
12 - kernel message
13 ------------[ cut here ]------------
14 kernel BUG at drivers/staging/erofs/xattr.c:59!
15 SMP PTI
16 CPU: 1 PID: 1170 Comm: getllxattr Not tainted 4.20.0-rc6+ #92
17 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-2.fc27 04/01/2014
18 RIP: 0010:init_inode_xattrs+0x22b/0x270
19 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$
20 <0f> 0b 48 89 ef e8 fb f6 9c ff 48 8b 45 08 a8 01 75 24 f0 ff 4d 34
21 RSP: 0018:ffffa03ac026bdf8 EFLAGS: 00010246
22 ------------[ cut here ]------------
23 ...
24 Call Trace:
25 erofs_listxattr+0x30/0x2c0
26 ? selinux_inode_listxattr+0x5a/0x80
27 ? kmem_cache_alloc+0x33/0x170
28 ? security_inode_listxattr+0x27/0x40
29 listxattr+0xaf/0xc0
30 path_listxattr+0x5a/0xa0
31 do_syscall_64+0x43/0xf0
32 entry_SYSCALL_64_after_hwframe+0x44/0xa9
33 ...
34 ---[ end trace 3c24b49408dc0c72 ]---
35
36 Fix it by checking ->xattr_isize in init_inode_xattrs(),
37 and it also fixes improper return value -ENOTSUPP
38 (it should be -ENODATA if xattr is enabled) for those inodes.
39
40 Fixes: b17500a0fdba ("staging: erofs: introduce xattr & acl support")
41 Cc: <stable@vger.kernel.org> # 4.19+
42 Reported-by: Li Guifu <bluce.liguifu@huawei.com>
43 Tested-by: Li Guifu <bluce.liguifu@huawei.com>
44 Reviewed-by: Chao Yu <yuchao0@huawei.com>
45 Signed-off-by: Gao Xiang <gaoxiang25@huawei.com>
46 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
47
48 ---
49 drivers/staging/erofs/inode.c | 8 ++++----
50 drivers/staging/erofs/xattr.c | 25 ++++++++++++++++++++-----
51 2 files changed, 24 insertions(+), 9 deletions(-)
52
53 --- a/drivers/staging/erofs/inode.c
54 +++ b/drivers/staging/erofs/inode.c
55 @@ -185,16 +185,16 @@ static int fill_inode(struct inode *inod
56 /* setup the new inode */
57 if (S_ISREG(inode->i_mode)) {
58 #ifdef CONFIG_EROFS_FS_XATTR
59 - if (vi->xattr_isize)
60 - inode->i_op = &erofs_generic_xattr_iops;
61 + inode->i_op = &erofs_generic_xattr_iops;
62 #endif
63 inode->i_fop = &generic_ro_fops;
64 } else if (S_ISDIR(inode->i_mode)) {
65 inode->i_op =
66 #ifdef CONFIG_EROFS_FS_XATTR
67 - vi->xattr_isize ? &erofs_dir_xattr_iops :
68 -#endif
69 + &erofs_dir_xattr_iops;
70 +#else
71 &erofs_dir_iops;
72 +#endif
73 inode->i_fop = &erofs_dir_fops;
74 } else if (S_ISLNK(inode->i_mode)) {
75 /* by default, page_get_link is used for symlink */
76 --- a/drivers/staging/erofs/xattr.c
77 +++ b/drivers/staging/erofs/xattr.c
78 @@ -56,7 +56,26 @@ static int init_inode_xattrs(struct inod
79 return 0;
80
81 vi = EROFS_V(inode);
82 - BUG_ON(!vi->xattr_isize);
83 +
84 + /*
85 + * bypass all xattr operations if ->xattr_isize is not greater than
86 + * sizeof(struct erofs_xattr_ibody_header), in detail:
87 + * 1) it is not enough to contain erofs_xattr_ibody_header then
88 + * ->xattr_isize should be 0 (it means no xattr);
89 + * 2) it is just to contain erofs_xattr_ibody_header, which is on-disk
90 + * undefined right now (maybe use later with some new sb feature).
91 + */
92 + if (vi->xattr_isize == sizeof(struct erofs_xattr_ibody_header)) {
93 + errln("xattr_isize %d of nid %llu is not supported yet",
94 + vi->xattr_isize, vi->nid);
95 + return -ENOTSUPP;
96 + } else if (vi->xattr_isize < sizeof(struct erofs_xattr_ibody_header)) {
97 + if (unlikely(vi->xattr_isize)) {
98 + DBG_BUGON(1);
99 + return -EIO; /* xattr ondisk layout error */
100 + }
101 + return -ENOATTR;
102 + }
103
104 sb = inode->i_sb;
105 sbi = EROFS_SB(sb);
106 @@ -422,7 +441,6 @@ static int erofs_xattr_generic_get(const
107 struct dentry *unused, struct inode *inode,
108 const char *name, void *buffer, size_t size)
109 {
110 - struct erofs_vnode *const vi = EROFS_V(inode);
111 struct erofs_sb_info *const sbi = EROFS_I_SB(inode);
112
113 switch (handler->flags) {
114 @@ -440,9 +458,6 @@ static int erofs_xattr_generic_get(const
115 return -EINVAL;
116 }
117
118 - if (!vi->xattr_isize)
119 - return -ENOATTR;
120 -
121 return erofs_getxattr(inode, handler->flags, name, buffer, size);
122 }
123