summaryrefslogtreecommitdiff
path: root/source3/modules/vfs_acl_xattr.c
diff options
context:
space:
mode:
authorUri Simchoni <uri@samba.org>2017-04-13 12:44:58 +0300
committerJeremy Allison <jra@samba.org>2017-04-18 04:41:16 +0200
commit05d83ccf7a6fecf963fcb980acd50cebfc0c3ea9 (patch)
tree40061bc5c95f43744e18121cb17ddff4d8ad217d /source3/modules/vfs_acl_xattr.c
parent7b775abd9278ae34110ec87d94a736be7f64884a (diff)
downloadsamba-05d83ccf7a6fecf963fcb980acd50cebfc0c3ea9.tar.gz
vfs_acl_xattr: avoid needlessly supplying a large buffer to getxattr()
When obtaining the security descriptor via getxattr(), first try optimistically to supply a buffer of 4K, and if that turns out to be too small, determine the correct buffer size. The previous behavior of falling back to a 64K buffer encountered problem with Linux prior to version 3.6, due to pyisical memory fragmentation. With those kernels, as long as the buffer is 8K or smaller, getting the xattr is much less prone to failure due to memory fragmentation. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12737 Signed-off-by: Uri Simchoni <uri@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org> Autobuild-User(master): Jeremy Allison <jra@samba.org> Autobuild-Date(master): Tue Apr 18 04:41:16 CEST 2017 on sn-devel-144
Diffstat (limited to 'source3/modules/vfs_acl_xattr.c')
-rw-r--r--source3/modules/vfs_acl_xattr.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/source3/modules/vfs_acl_xattr.c b/source3/modules/vfs_acl_xattr.c
index 85b9a0d660a..421860b2adf 100644
--- a/source3/modules/vfs_acl_xattr.c
+++ b/source3/modules/vfs_acl_xattr.c
@@ -72,7 +72,7 @@ static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
const struct smb_filename *smb_fname,
DATA_BLOB *pblob)
{
- size_t size = 1024;
+ size_t size = 4096;
uint8_t *val = NULL;
uint8_t *tmp;
ssize_t sizeret;
@@ -91,22 +91,38 @@ static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
sizeret =
getxattr_do(handle, fsp, smb_fname, XATTR_NTACL_NAME, val, size);
- /* Max ACL size is 65536 bytes. */
- if (sizeret == -1) {
- if ((errno == ERANGE) && (size != 65536)) {
- /* Too small, try again. */
- size = 65536;
- goto again;
- }
+ if (sizeret >= 0) {
+ pblob->data = val;
+ pblob->length = sizeret;
+ return NT_STATUS_OK;
+ }
- /* Real error - exit here. */
- TALLOC_FREE(val);
- return map_nt_error_from_unix(errno);
+ if (errno != ERANGE) {
+ goto err;
}
- pblob->data = val;
- pblob->length = sizeret;
- return NT_STATUS_OK;
+ /* Too small, try again. */
+ sizeret =
+ getxattr_do(handle, fsp, smb_fname, XATTR_NTACL_NAME, NULL, 0);
+ if (sizeret < 0) {
+ goto err;
+ }
+
+ if (size < sizeret) {
+ size = sizeret;
+ }
+
+ if (size > 65536) {
+ /* Max ACL size is 65536 bytes. */
+ errno = ERANGE;
+ goto err;
+ }
+
+ goto again;
+ err:
+ /* Real error - exit here. */
+ TALLOC_FREE(val);
+ return map_nt_error_from_unix(errno);
}
/*******************************************************************