CVE-2021-44142: libadouble: harden ad_unpack_xattrs()
authorRalph Boehme <slow@samba.org>
Fri, 26 Nov 2021 06:19:32 +0000 (07:19 +0100)
committerJule Anger <janger@samba.org>
Sun, 30 Jan 2022 13:08:00 +0000 (14:08 +0100)
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>
source3/lib/adouble.c

index 42b2e808d66743a92b7c0028b88e65e4d09012a4..48621feb530d7df7c4b334f0e4e4b72bd19d2791 100644 (file)
@@ -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;