summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2021-11-26 07:19:32 +0100
committerJule Anger <janger@samba.org>2022-01-30 14:08:00 +0100
commitb3b76222cfba5d162843b14b55570a02573c8ce8 (patch)
tree16605394f99b4f69ee13d998273517d316f23af7
parent9eba87ce4b47488f1422248b8d4ad9b37ae26899 (diff)
downloadsamba-b3b76222cfba5d162843b14b55570a02573c8ce8.tar.gz
CVE-2021-44142: libadouble: harden ad_unpack_xattrs()
This ensures ad_unpack_xattrs() is only called for an ad_type of ADOUBLE_RSRC, which is used for parsing ._ AppleDouble sidecar files, and the buffer ad->ad_data is AD_XATTR_MAX_HDR_SIZE bytes large which is a prerequisite for all buffer out-of-bounds access checks in ad_unpack_xattrs(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14914 Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
-rw-r--r--source3/lib/adouble.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/source3/lib/adouble.c b/source3/lib/adouble.c
index 42b2e808d66..48621feb530 100644
--- a/source3/lib/adouble.c
+++ b/source3/lib/adouble.c
@@ -707,14 +707,27 @@ static bool ad_pack(struct vfs_handle_struct *handle,
static bool ad_unpack_xattrs(struct adouble *ad)
{
struct ad_xattr_header *h = &ad->adx_header;
+ size_t bufsize = talloc_get_size(ad->ad_data);
const char *p = ad->ad_data;
uint32_t hoff;
uint32_t i;
+ if (ad->ad_type != ADOUBLE_RSRC) {
+ return false;
+ }
+
if (ad_getentrylen(ad, ADEID_FINDERI) <= ADEDLEN_FINDERI) {
return true;
}
+ /*
+ * Ensure the buffer ad->ad_data was allocated by ad_alloc() for an
+ * ADOUBLE_RSRC type (._ AppleDouble file on-disk).
+ */
+ if (bufsize != AD_XATTR_MAX_HDR_SIZE) {
+ return false;
+ }
+
/* 2 bytes padding */
hoff = ad_getentryoff(ad, ADEID_FINDERI) + ADEDLEN_FINDERI + 2;
@@ -964,9 +977,11 @@ static bool ad_unpack(struct adouble *ad, const size_t nentries,
ad->ad_eid[eid].ade_len = len;
}
- ok = ad_unpack_xattrs(ad);
- if (!ok) {
- return false;
+ if (ad->ad_type == ADOUBLE_RSRC) {
+ ok = ad_unpack_xattrs(ad);
+ if (!ok) {
+ return false;
+ }
}
return true;