diff options
author | Chao Yu | 2019-03-05 12:32:26 +0100 |
---|---|---|
committer | Greg Kroah-Hartman | 2019-04-05 22:32:55 +0200 |
commit | 198c99857b302ad46a4717dc6351b069fc5ac17f (patch) | |
tree | b3fd275f186b9f06244cb92efeb23a7dabd347bc /fs/f2fs/xattr.c | |
parent | h8300: use cc-cross-prefix instead of hardcoding h8300-unknown-linux- (diff) | |
download | kernel-qcow2-linux-198c99857b302ad46a4717dc6351b069fc5ac17f.tar.gz kernel-qcow2-linux-198c99857b302ad46a4717dc6351b069fc5ac17f.tar.xz kernel-qcow2-linux-198c99857b302ad46a4717dc6351b069fc5ac17f.zip |
f2fs: fix to adapt small inline xattr space in __find_inline_xattr()
[ Upstream commit 2c28aba8b2e2a51749fa66e01b68e1cd5b53e022 ]
With below testcase, we will fail to find existed xattr entry:
1. mkfs.f2fs -O extra_attr -O flexible_inline_xattr /dev/zram0
2. mount -t f2fs -o inline_xattr_size=1 /dev/zram0 /mnt/f2fs/
3. touch /mnt/f2fs/file
4. setfattr -n "user.name" -v 0 /mnt/f2fs/file
5. getfattr -n "user.name" /mnt/f2fs/file
/mnt/f2fs/file: user.name: No such attribute
The reason is for inode which has very small inline xattr size,
__find_inline_xattr() will fail to traverse any entry due to first
entry may not be loaded from xattr node yet, later, we may skip to
check entire xattr datas in __find_xattr(), result in such wrong
condition.
This patch adds condition to check such case to avoid this issue.
Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'fs/f2fs/xattr.c')
-rw-r--r-- | fs/f2fs/xattr.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 087e53a2d96c..409a637f7a92 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -227,11 +227,11 @@ static struct f2fs_xattr_entry *__find_inline_xattr(struct inode *inode, { struct f2fs_xattr_entry *entry; unsigned int inline_size = inline_xattr_size(inode); + void *max_addr = base_addr + inline_size; list_for_each_xattr(entry, base_addr) { - if ((void *)entry + sizeof(__u32) > base_addr + inline_size || - (void *)XATTR_NEXT_ENTRY(entry) + sizeof(__u32) > - base_addr + inline_size) { + if ((void *)entry + sizeof(__u32) > max_addr || + (void *)XATTR_NEXT_ENTRY(entry) > max_addr) { *last_addr = entry; return NULL; } @@ -242,6 +242,13 @@ static struct f2fs_xattr_entry *__find_inline_xattr(struct inode *inode, if (!memcmp(entry->e_name, name, len)) break; } + + /* inline xattr header or entry across max inline xattr size */ + if (IS_XATTR_LAST_ENTRY(entry) && + (void *)entry + sizeof(__u32) > max_addr) { + *last_addr = entry; + return NULL; + } return entry; } |