* [PATCH v3] smb: client: fix heap overflow in cifs_do_set_acl()
@ 2026-08-26 15:06 Frank Sorenson
0 siblings, 0 replies; only message in thread
From: Frank Sorenson @ 2026-08-26 15:06 UTC (permalink / raw)
To: linux-cifs; +Cc: pc, linkinjeon, stable
cifs_set_acl() validates ACL size using posix_acl_xattr_size():
4 + (count * 8) // 4-byte header + 8 bytes per ACE
cifs_do_set_acl() then calls posix_acl_to_cifs() to write the CIFS
wire format into the same buffer:
6 + (count * 10) // 6-byte header + 10 bytes per ACE
An ACL that passes the xattr-based check in cifs_set_acl() can
overflow the heap when posix_acl_to_cifs() writes the larger CIFS
format.
Validate the CIFS format size against the remaining buffer space and
USHRT_MAX before converting--data_count is __u16, so sizes above
USHRT_MAX truncate the on-wire packet length, causing the server to
apply a partial ACL. Replace MaxDataCount = 1000 with
min(CIFSMaxBufSize, USHRT_MAX).
Fixes: dc1af4c4b4721 ("cifs: implement set acl method")
Cc: stable@vger.kernel.org
Signed-off-by: Frank Sorenson <sorenson@redhat.com>
---
v3 changes:
- change header size to use MAX_HEADER_SIZE helper
v2 changes:
- Add USHRT_MAX bound to prevent u16 truncation of data_count for ACLs
with more than 6553 entries, which would cause a partial ACL to be
silently applied on the server
- limit MaxDataCount to min(CIFSMaxBufSize, USHRT_MAX)
fs/smb/client/cifssmb.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c
index f5aad5f61dce..230af243247c 100644
--- a/fs/smb/client/cifssmb.c
+++ b/fs/smb/client/cifssmb.c
@@ -3555,6 +3555,7 @@ int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
int rc = 0;
int bytes_returned = 0;
__u16 params, byte_count, data_count, param_offset, offset;
+ size_t cifs_acl_size, bytes_available;
cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
setAclRetry:
@@ -3574,8 +3575,7 @@ int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
}
params = 6 + name_len;
pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find max SMB size from sess */
- pSMB->MaxDataCount = cpu_to_le16(1000);
+ pSMB->MaxDataCount = cpu_to_le16(min_t(unsigned int, CIFSMaxBufSize, USHRT_MAX));
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
@@ -3587,6 +3587,15 @@ int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
parm_data = ((char *)pSMB) + offset;
pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ /* make sure we can fit the larger cifs_posix_aces in the buffer */
+ cifs_acl_size = sizeof(struct cifs_posix_acl) +
+ (acl->a_count * sizeof(struct cifs_posix_ace));
+ bytes_available = (CIFSMaxBufSize + MAX_HEADER_SIZE(tcon->ses->server)) - offset;
+ if (cifs_acl_size > bytes_available || cifs_acl_size > USHRT_MAX) {
+ rc = -E2BIG;
+ goto setACLerrorExit;
+ }
+
/* convert to on the wire format for POSIX ACL */
data_count = posix_acl_to_cifs(parm_data, acl, acl_type);
--
2.55.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-08-26 15:07 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-26 15:06 [PATCH v3] smb: client: fix heap overflow in cifs_do_set_acl() Frank Sorenson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox