Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ksmbd: use check_add_overflow() to prevent u16 DACL size overflow

set_posix_acl_entries_dacl() and set_ntacl_dacl() accumulate ACE sizes
in u16 variables. When a file has many POSIX ACL entries, the
accumulated size can wrap past 65535, causing the pointer arithmetic
(char *)pndace + *size to land within already-written ACEs. Subsequent
writes then overwrite earlier entries, and pndacl->size gets a
truncated value.

Use check_add_overflow() at each accumulation point to detect the
wrap before it corrupts the buffer, consistent with existing
check_mul_overflow() usage elsewhere in smbacl.c.

Cc: stable@vger.kernel.org
Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>

authored by

Tristan Madani and committed by
Steve French
299f962c 1baff47b

+12 -4
+12 -4
fs/smb/server/smbacl.c
··· 596 596 struct smb_sid *sid; 597 597 struct smb_ace *ntace; 598 598 int i, j; 599 + u16 ace_sz; 599 600 600 601 if (!fattr->cf_acls) 601 602 goto posix_default_acl; ··· 641 640 flags = 0x03; 642 641 643 642 ntace = (struct smb_ace *)((char *)pndace + *size); 644 - *size += fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, flags, 643 + ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, flags, 645 644 pace->e_perm, 0777); 645 + if (check_add_overflow(*size, ace_sz, size)) 646 + break; 646 647 (*num_aces)++; 647 648 if (pace->e_tag == ACL_USER) 648 649 ntace->access_req |= ··· 653 650 if (S_ISDIR(fattr->cf_mode) && 654 651 (pace->e_tag == ACL_USER || pace->e_tag == ACL_GROUP)) { 655 652 ntace = (struct smb_ace *)((char *)pndace + *size); 656 - *size += fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, 653 + ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, 657 654 0x03, pace->e_perm, 0777); 655 + if (check_add_overflow(*size, ace_sz, size)) 656 + break; 658 657 (*num_aces)++; 659 658 if (pace->e_tag == ACL_USER) 660 659 ntace->access_req |= ··· 696 691 } 697 692 698 693 ntace = (struct smb_ace *)((char *)pndace + *size); 699 - *size += fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, 0x0b, 694 + ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, 0x0b, 700 695 pace->e_perm, 0777); 696 + if (check_add_overflow(*size, ace_sz, size)) 697 + break; 701 698 (*num_aces)++; 702 699 if (pace->e_tag == ACL_USER) 703 700 ntace->access_req |= ··· 735 728 break; 736 729 737 730 memcpy((char *)pndace + size, ntace, nt_ace_size); 738 - size += nt_ace_size; 731 + if (check_add_overflow(size, nt_ace_size, &size)) 732 + break; 739 733 aces_size -= nt_ace_size; 740 734 ntace = (struct smb_ace *)((char *)ntace + nt_ace_size); 741 735 num_aces++;