Allow internal reads of huge xattrs

The Linux xattr syscalls don't support values of more than 64k, but the
module still needs to use bigger xattrs internally to support compressed
files. When I refactored the xattr code in commit 9b71ea9b0f ("Use the
common dstream code to read dstream xattrs"), it seems that I thought I
could simplify an overflow check on the xattr size by simply checking
against this upper limit, but that broke compressed reads.

Revert the bad change, and put the xattr size check directly inside the
apfs_xattr_get() handler, where it won't bother internal code.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
This commit is contained in:
Ernesto A. Fernández committed 2021-09-21 17:25:41 -03:00
1 parent 9c117a8126
commit 362c4e32ab
2 files changed
+7 -8

No files matched your search

-2
View File
@@ -862,8 +862,6 @@ extern int ____apfs_xattr_get(struct inode *inode, const char *name, void *buffe
size_t size, bool only_whole);
extern int __apfs_xattr_get(struct inode *inode, const char *name, void *buffer,
size_t size);
extern int apfs_xattr_get(struct inode *inode, const char *name, void *buffer,
size_t size);
extern int apfs_delete_all_xattrs(struct inode *inode);
extern int apfs_xattr_set(struct inode *inode, const char *name, const void *value,
size_t size, int flags);
+7 -6
View File
@@ -104,11 +104,11 @@ static int apfs_xattr_extents_read(struct inode *parent,
return -ENOMEM;
apfs_dstream_from_xattr(sb, xattr, dstream);
if (dstream->ds_size > XATTR_SIZE_MAX) {
ret = -E2BIG;
goto out;
}
length = dstream->ds_size;
if (length < 0 || length < dstream->ds_size) {
/* TODO: avoid overflow here for huge compressed files */
return -E2BIG;
}
if (!buffer) {
/* All we want is the length */
@@ -269,8 +269,7 @@ done:
* Returns the number of bytes used/required, or a negative error code in case
* of failure.
*/
int apfs_xattr_get(struct inode *inode, const char *name, void *buffer,
size_t size)
static int apfs_xattr_get(struct inode *inode, const char *name, void *buffer, size_t size)
{
struct apfs_nxsb_info *nxi = APFS_NXI(inode->i_sb);
int ret;
@@ -278,6 +277,8 @@ int apfs_xattr_get(struct inode *inode, const char *name, void *buffer,
down_read(&nxi->nx_big_sem);
ret = __apfs_xattr_get(inode, name, buffer, size);
up_read(&nxi->nx_big_sem);
if (ret > XATTR_SIZE_MAX)
return -E2BIG;
return ret;
}