From: Ralph Boehme Date: Tue, 10 Oct 2017 14:04:29 +0000 (+0200) Subject: vfs_fruit: allocate ad_data buffer up to AD_XATTR_MAX_HDR_SIZE bytes X-Git-Tag: tevent-0.9.34~216 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ab8d01959b906d0b2873357f836bff72d209ff98;p=thirdparty%2Fsamba.git vfs_fruit: allocate ad_data buffer up to AD_XATTR_MAX_HDR_SIZE bytes This is in preperation of reading potential xattr header data from the AppleDouble file, not just reading a fixed amount of bytes. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13076 Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke --- diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index 37e8d8d24f9..aea3ad682eb 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -578,6 +578,10 @@ static bool ad_pack(struct adouble *ad) uint32_t offset = 0; bufsize = talloc_get_size(ad->ad_data); + if (bufsize < AD_DATASZ_DOT_UND) { + DBG_ERR("bad buffer size [0x%" PRIx32 "]\n", bufsize); + return false; + } if (offset + ADEDLEN_MAGIC < offset || offset + ADEDLEN_MAGIC >= bufsize) { @@ -1021,22 +1025,44 @@ static ssize_t ad_read_rsrc_adouble(struct adouble *ad, char *p_ad = NULL; char *p_meta_ad = NULL; ssize_t len; + size_t size; int ret; bool ok; - len = sys_pread(ad->ad_fd, ad->ad_data, AD_DATASZ_DOT_UND, 0); - if (len != AD_DATASZ_DOT_UND) { - DBG_NOTICE("%s %s: bad size: %zd\n", - smb_fname->base_name, strerror(errno), len); - return -1; - } - ret = sys_fstat(ad->ad_fd, &sbuf, lp_fake_directory_create_times( SNUM(ad->ad_handle->conn))); if (ret != 0) { return -1; } + /* + * AppleDouble file header content and size, two cases: + * + * - without xattrs it is exactly AD_DATASZ_DOT_UND (82) bytes large + * - with embedded xattrs it can be larger, up to AD_XATTR_MAX_HDR_SIZE + * + * Read as much as we can up to AD_XATTR_MAX_HDR_SIZE. + */ + size = sbuf.st_ex_size; + if (size > talloc_array_length(ad->ad_data)) { + if (size > AD_XATTR_MAX_HDR_SIZE) { + size = AD_XATTR_MAX_HDR_SIZE; + } + p_ad = talloc_realloc(ad, ad->ad_data, char, size); + if (p_ad == NULL) { + return -1; + } + ad->ad_data = p_ad; + } + + len = sys_pread(ad->ad_fd, ad->ad_data, + talloc_array_length(ad->ad_data), 0); + if (len != talloc_array_length(ad->ad_data)) { + DBG_NOTICE("%s %s: bad size: %zd\n", + smb_fname->base_name, strerror(errno), len); + return -1; + } + /* Now parse entries */ ok = ad_unpack(ad, ADEID_NUM_DOT_UND, sbuf.st_ex_size); if (!ok) { @@ -1452,9 +1478,9 @@ static int ad_fset(struct adouble *ad, files_struct *fsp) len = SMB_VFS_NEXT_PWRITE(ad->ad_handle, fsp, ad->ad_data, - talloc_get_size(ad->ad_data), + AD_DATASZ_DOT_UND, 0); - if (len != (ssize_t)talloc_get_size(ad->ad_data)) { + if (len != AD_DATASZ_DOT_UND) { DBG_ERR("short write on %s: %zd", fsp_str_dbg(fsp), len); return -1; }