xattr: Avoid dynamically allocating memory in getxattr

Although the maximum xattr size is too big to fit on the stack (64 KiB),
we can still fulfill most getxattr requests with a 4 KiB stack
allocation, thereby improving performance.

Change-Id: I36798b527d7641597c44c1d7035981a7477e5d4b
Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com>
Signed-off-by: Yaroslav Furman <yaro330@gmail.com>
Signed-off-by: Richard Raya <rdxzv.dev@gmail.com>
This commit is contained in:
Sultan Alsawaf 2019-07-02 01:54:39 -07:00 committed by Richard Raya
parent 15c8a438c6
commit 9d446ea713

View File

@ -601,6 +601,7 @@ getxattr(struct dentry *d, const char __user *name, void __user *value,
ssize_t error;
void *kvalue = NULL;
char kname[XATTR_NAME_MAX + 1];
char kvalue_onstack[SZ_4K] __aligned(8);
error = strncpy_from_user(kname, name, sizeof(kname));
if (error == 0 || error == sizeof(kname))
@ -609,11 +610,16 @@ getxattr(struct dentry *d, const char __user *name, void __user *value,
return error;
if (size) {
if (size > XATTR_SIZE_MAX)
size = XATTR_SIZE_MAX;
kvalue = kvzalloc(size, GFP_KERNEL);
if (!kvalue)
return -ENOMEM;
if (size <= ARRAY_SIZE(kvalue_onstack)) {
kvalue = kvalue_onstack;
memset(kvalue, 0, size);
} else {
if (size > XATTR_SIZE_MAX)
size = XATTR_SIZE_MAX;
kvalue = kvzalloc(size, GFP_KERNEL);
if (!kvalue)
return -ENOMEM;
}
}
error = vfs_getxattr(d, kname, kvalue, size);
@ -629,7 +635,8 @@ getxattr(struct dentry *d, const char __user *name, void __user *value,
error = -E2BIG;
}
kvfree(kvalue);
if (kvalue != kvalue_onstack)
kvfree(kvalue);
return error;
}