|
8 | 8 | #include <linux/compat.h> |
9 | 9 | #include <trace/events/erofs.h> |
10 | 10 |
|
11 | | -static int erofs_fill_symlink(struct inode *inode, void *kaddr, |
12 | | - unsigned int m_pofs) |
| 11 | +static int erofs_fill_symlink(struct inode *inode, void *bptr, unsigned int ofs) |
13 | 12 | { |
14 | 13 | struct erofs_inode *vi = EROFS_I(inode); |
15 | | - loff_t off; |
16 | | - |
17 | | - m_pofs += vi->xattr_isize; |
18 | | - /* check if it cannot be handled with fast symlink scheme */ |
19 | | - if (vi->datalayout != EROFS_INODE_FLAT_INLINE || |
20 | | - check_add_overflow(m_pofs, inode->i_size, &off) || |
21 | | - off > i_blocksize(inode)) |
22 | | - return 0; |
23 | | - |
24 | | - inode->i_link = kmemdup_nul(kaddr + m_pofs, inode->i_size, GFP_KERNEL); |
25 | | - return inode->i_link ? 0 : -ENOMEM; |
| 14 | + char *link; |
| 15 | + loff_t end; |
| 16 | + |
| 17 | + ofs += vi->xattr_isize; |
| 18 | + /* check whether the symlink data is small enough to be inlined */ |
| 19 | + if (vi->datalayout == EROFS_INODE_FLAT_INLINE && |
| 20 | + !check_add_overflow(ofs, inode->i_size, &end) && |
| 21 | + end <= i_blocksize(inode)) { |
| 22 | + link = kmemdup_nul(bptr + ofs, inode->i_size, GFP_KERNEL); |
| 23 | + if (!link) |
| 24 | + return -ENOMEM; |
| 25 | + if (unlikely(!inode->i_size || strlen(link) != inode->i_size)) { |
| 26 | + erofs_err(inode->i_sb, "invalid fast symlink size %llu @ nid %llu", |
| 27 | + inode->i_size | 0ULL, vi->nid); |
| 28 | + kfree(link); |
| 29 | + return -EFSCORRUPTED; |
| 30 | + } |
| 31 | + inode_set_cached_link(inode, link, inode->i_size); |
| 32 | + } |
| 33 | + return 0; |
26 | 34 | } |
27 | 35 |
|
28 | 36 | static int erofs_read_inode(struct inode *inode) |
|
0 commit comments