diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-12-31 20:41:37 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-12-31 20:41:37 +0300 |
commit | 9ab97aea85cca43a6aedc90e0d1feba91eebe1ad (patch) | |
tree | ee469150be8c0f7e3be5a76255b3756a1401987f /fs/f2fs/xattr.c | |
parent | 195303136f192d37b89e20a8d1d2670d0d825266 (diff) | |
parent | 64beba0558fce7b59e9a8a7afd77290e82a22163 (diff) | |
download | linux-9ab97aea85cca43a6aedc90e0d1feba91eebe1ad.tar.xz |
Merge tag 'f2fs-for-4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs
Pull f2fs updates from Jaegeuk Kim:
"In this round, we've focused on bug fixes since Pixel devices have
been shipping with f2fs. Some of them were related to hardware
encryption support which are actually not an issue in mainline, but
would be better to merge them in order to avoid potential bugs.
Enhancements:
- do GC sub-sections when the section is large
- add a flag in ioctl(SHUTDOWN) to trigger fsck for QA
- use kvmalloc() in order to give another chance to avoid ENOMEM
Bug fixes:
- fix accessing memory boundaries in a malformed iamge
- GC gives stale unencrypted block
- GC counts in large sections
- detect idle time more precisely
- block allocation of DIO writes
- race conditions between write_begin and write_checkpoint
- allow GCs for node segments via ioctl()
There are various clean-ups and minor bug fixes as well"
* tag 'f2fs-for-4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (43 commits)
f2fs: sanity check of xattr entry size
f2fs: fix use-after-free issue when accessing sbi->stat_info
f2fs: check PageWriteback flag for ordered case
f2fs: fix validation of the block count in sanity_check_raw_super
f2fs: fix missing unlock(sbi->gc_mutex)
f2fs: fix to dirty inode synchronously
f2fs: clean up structure extent_node
f2fs: fix block address for __check_sit_bitmap
f2fs: fix sbi->extent_list corruption issue
f2fs: clean up checkpoint flow
f2fs: flush stale issued discard candidates
f2fs: correct wrong spelling, issing_*
f2fs: use kvmalloc, if kmalloc is failed
f2fs: remove redundant comment of unused wio_mutex
f2fs: fix to reorder set_page_dirty and wait_on_page_writeback
f2fs: clear PG_writeback if IPU failed
f2fs: add an ioctl() to explicitly trigger fsck later
f2fs: avoid frequent costly fsck triggers
f2fs: fix m_may_create to make OPU DIO write correctly
f2fs: fix to update new block address correctly for OPU
...
Diffstat (limited to 'fs/f2fs/xattr.c')
-rw-r--r-- | fs/f2fs/xattr.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 7261245c208d..18d5ffbc5e8c 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -288,7 +288,7 @@ static int read_xattr_block(struct inode *inode, void *txattr_addr) static int lookup_all_xattrs(struct inode *inode, struct page *ipage, unsigned int index, unsigned int len, const char *name, struct f2fs_xattr_entry **xe, - void **base_addr) + void **base_addr, int *base_size) { void *cur_addr, *txattr_addr, *last_addr = NULL; nid_t xnid = F2FS_I(inode)->i_xattr_nid; @@ -299,8 +299,8 @@ static int lookup_all_xattrs(struct inode *inode, struct page *ipage, if (!size && !inline_size) return -ENODATA; - txattr_addr = f2fs_kzalloc(F2FS_I_SB(inode), - inline_size + size + XATTR_PADDING_SIZE, GFP_NOFS); + *base_size = inline_size + size + XATTR_PADDING_SIZE; + txattr_addr = f2fs_kzalloc(F2FS_I_SB(inode), *base_size, GFP_NOFS); if (!txattr_addr) return -ENOMEM; @@ -312,8 +312,10 @@ static int lookup_all_xattrs(struct inode *inode, struct page *ipage, *xe = __find_inline_xattr(inode, txattr_addr, &last_addr, index, len, name); - if (*xe) + if (*xe) { + *base_size = inline_size; goto check; + } } /* read from xattr node block */ @@ -415,7 +417,7 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize, } f2fs_wait_on_page_writeback(ipage ? ipage : in_page, - NODE, true); + NODE, true, true); /* no need to use xattr node block */ if (hsize <= inline_size) { err = f2fs_truncate_xattr_node(inode); @@ -439,7 +441,7 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize, goto in_page_out; } f2fs_bug_on(sbi, new_nid); - f2fs_wait_on_page_writeback(xpage, NODE, true); + f2fs_wait_on_page_writeback(xpage, NODE, true, true); } else { struct dnode_of_data dn; set_new_dnode(&dn, inode, NULL, NULL, new_nid); @@ -474,6 +476,7 @@ int f2fs_getxattr(struct inode *inode, int index, const char *name, int error = 0; unsigned int size, len; void *base_addr = NULL; + int base_size; if (name == NULL) return -EINVAL; @@ -484,7 +487,7 @@ int f2fs_getxattr(struct inode *inode, int index, const char *name, down_read(&F2FS_I(inode)->i_xattr_sem); error = lookup_all_xattrs(inode, ipage, index, len, name, - &entry, &base_addr); + &entry, &base_addr, &base_size); up_read(&F2FS_I(inode)->i_xattr_sem); if (error) return error; @@ -498,6 +501,11 @@ int f2fs_getxattr(struct inode *inode, int index, const char *name, if (buffer) { char *pval = entry->e_name + entry->e_name_len; + + if (base_size - (pval - (char *)base_addr) < size) { + error = -ERANGE; + goto out; + } memcpy(buffer, pval, size); } error = size; |