From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BC9BE303CB0; Fri, 15 May 2026 16:08:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778861288; cv=none; b=pQZ1+GmNZV/7CnryR7WSGCMSUAqKOsuWkWo8mTAbwpgWjGVOZrX1JceKZGxo2xbPu+V3dxjNYJIZuAVadmeFtnYSacELGL6wu38fxjE7rRBr6cG8BYMG4kumi3GIBSfdm00iM4ZWF6OB3UZcsvUcV+46vDcunTXs47NoMpcGyII= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778861288; c=relaxed/simple; bh=y4DdxbbsrekDmz+CbF3okfkbb5icN3AH0ApyosmLuW0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mR5Y1uBo+l3lbXfUzXzBUR6KnXPi/BnT6JbTQBVpbOmWn0BUy750sMWCBkZcbTleYGwmOAzU/lYMX3tXZEZkHDMxN2Iec04UjbqJoka1j9GV+2B1VOts5pPm1sYSK/tcL7/67IrdcAUtsUOP8GQog+EknkeP9Tz/h8BOv+SWpTY= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=Ig0TD3cn; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="Ig0TD3cn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 539E6C2BCB0; Fri, 15 May 2026 16:08:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1778861288; bh=y4DdxbbsrekDmz+CbF3okfkbb5icN3AH0ApyosmLuW0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ig0TD3cn5T/QdXMjBopFf7nJJiLTxN6WRZwgMKAYnqXTojDneQ7UBYISudwE48ysn Fc9lHMDQ2kJl1VnoPXpZDnthU7EElNHvIPrVyozhQ11bDtPYDLKoDG4i2+yqSKZ+FT I3F9fqxiwwmhoqJx+jmJU9JlWc5P90Xo3jHxZ5WU= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Michael Bommarito , Steve French Subject: [PATCH 6.6 271/474] smb: client: validate dacloffset before building DACL pointers Date: Fri, 15 May 2026 17:46:20 +0200 Message-ID: <20260515154720.866222486@linuxfoundation.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260515154715.053014143@linuxfoundation.org> References: <20260515154715.053014143@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.6-stable review patch. If anyone has any objections, please let me know. ------------------ From: Michael Bommarito commit f98b48151cc502ada59d9778f0112d21f2586ca3 upstream. parse_sec_desc(), build_sec_desc(), and the chown path in id_mode_to_cifs_acl() all add the server-supplied dacloffset to pntsd before proving a DACL header fits inside the returned security descriptor. On 32-bit builds a malicious server can return dacloffset near U32_MAX, wrap the derived DACL pointer below end_of_acl, and then slip past the later pointer-based bounds checks. build_sec_desc() and id_mode_to_cifs_acl() can then dereference DACL fields from the wrapped pointer in the chmod/chown rewrite paths. Validate dacloffset numerically before building any DACL pointer and reuse the same helper at the three DACL entry points. Fixes: bc3e9dd9d104 ("cifs: Change SIDs in ACEs while transferring file ownership.") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Michael Bommarito Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/smb/client/cifsacl.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) --- a/fs/smb/client/cifsacl.c +++ b/fs/smb/client/cifsacl.c @@ -1216,6 +1216,17 @@ static int parse_sid(struct smb_sid *psi return 0; } +static bool dacl_offset_valid(unsigned int acl_len, __u32 dacloffset) +{ + if (acl_len < sizeof(struct smb_acl)) + return false; + + if (dacloffset < sizeof(struct smb_ntsd)) + return false; + + return dacloffset <= acl_len - sizeof(struct smb_acl); +} + /* Convert CIFS ACL to POSIX form */ static int parse_sec_desc(struct cifs_sb_info *cifs_sb, @@ -1236,7 +1247,6 @@ static int parse_sec_desc(struct cifs_sb group_sid_ptr = (struct smb_sid *)((char *)pntsd + le32_to_cpu(pntsd->gsidoffset)); dacloffset = le32_to_cpu(pntsd->dacloffset); - dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset); cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n", pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset), le32_to_cpu(pntsd->gsidoffset), @@ -1267,11 +1277,18 @@ static int parse_sec_desc(struct cifs_sb return rc; } - if (dacloffset) + if (dacloffset) { + if (!dacl_offset_valid(acl_len, dacloffset)) { + cifs_dbg(VFS, "Server returned illegal DACL offset\n"); + return -EINVAL; + } + + dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset); parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr, fattr, get_mode_from_special_sid); - else + } else { cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */ + } return rc; } @@ -1294,6 +1311,11 @@ static int build_sec_desc(struct smb_nts dacloffset = le32_to_cpu(pntsd->dacloffset); if (dacloffset) { + if (!dacl_offset_valid(secdesclen, dacloffset)) { + cifs_dbg(VFS, "Server returned illegal DACL offset\n"); + return -EINVAL; + } + dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset); if (end_of_acl < (char *)dacl_ptr + le16_to_cpu(dacl_ptr->size)) { cifs_dbg(VFS, "Server returned illegal ACL size\n"); @@ -1668,6 +1690,12 @@ id_mode_to_cifs_acl(struct inode *inode, nsecdesclen = sizeof(struct smb_ntsd) + (sizeof(struct smb_sid) * 2); dacloffset = le32_to_cpu(pntsd->dacloffset); if (dacloffset) { + if (!dacl_offset_valid(secdesclen, dacloffset)) { + cifs_dbg(VFS, "Server returned illegal DACL offset\n"); + rc = -EINVAL; + goto id_mode_to_cifs_acl_exit; + } + dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset); if (mode_from_sid) nsecdesclen += @@ -1704,6 +1732,7 @@ id_mode_to_cifs_acl(struct inode *inode, rc = ops->set_acl(pnntsd, nsecdesclen, inode, path, aclflag); cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc); } +id_mode_to_cifs_acl_exit: cifs_put_tlink(tlink); kfree(pnntsd);