1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-24 13:57:43 +03:00

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
This commit is contained in:
Uri Simchoni 2017-04-13 12:44:58 +03:00 committed by Jeremy Allison
parent 7b775abd92
commit 05d83ccf7a

View File

@ -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;
}
/* Real error - exit here. */
TALLOC_FREE(val);
return map_nt_error_from_unix(errno);
if (sizeret >= 0) {
pblob->data = val;
pblob->length = sizeret;
return NT_STATUS_OK;
}
pblob->data = val;
pblob->length = sizeret;
return NT_STATUS_OK;
if (errno != ERANGE) {
goto err;
}
/* 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);
}
/*******************************************************************