diff options
author | Uri Simchoni <uri@samba.org> | 2017-04-13 12:44:58 +0300 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2017-04-18 04:41:16 +0200 |
commit | 05d83ccf7a6fecf963fcb980acd50cebfc0c3ea9 (patch) | |
tree | 40061bc5c95f43744e18121cb17ddff4d8ad217d /source3/modules/vfs_acl_xattr.c | |
parent | 7b775abd9278ae34110ec87d94a736be7f64884a (diff) | |
download | samba-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.c | 44 |
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); } /******************************************************************* |