Skip to content

Commit 69f030c

Browse files
kappamosssmfrench
authored andcommitted
ksmbd: validate SID in parent security descriptor during ACL inheritance
Introduce smb_validate_ntsd_sid() helper to safely validate Owner SID and Group SID inside the NT Security Descriptor (smb_ntsd) retrieved from the parent directory. Cc: stable@vger.kernel.org Signed-off-by: Junyi Liu <moss80199@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent 3515503 commit 69f030c

1 file changed

Lines changed: 50 additions & 16 deletions

File tree

fs/smb/server/smbacl.c

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,40 @@ static int smb_append_inherited_ace(struct smb_ace **ace, int *nt_size,
10961096
return 0;
10971097
}
10981098

1099+
static int smb_validate_ntsd_sid(struct smb_ntsd *pntsd, size_t pntsd_size,
1100+
unsigned int sid_offset, struct smb_sid **sid,
1101+
size_t *sid_size)
1102+
{
1103+
size_t sid_end;
1104+
1105+
*sid = NULL;
1106+
*sid_size = 0;
1107+
1108+
if (!sid_offset)
1109+
return 0;
1110+
1111+
if (sid_offset < sizeof(struct smb_ntsd) ||
1112+
check_add_overflow(sid_offset, (size_t)CIFS_SID_BASE_SIZE,
1113+
&sid_end) ||
1114+
sid_end > pntsd_size)
1115+
return -EINVAL;
1116+
1117+
*sid = (struct smb_sid *)((char *)pntsd + sid_offset);
1118+
if ((*sid)->num_subauth > SID_MAX_SUB_AUTHORITIES)
1119+
return -EINVAL;
1120+
1121+
if (check_add_overflow((size_t)CIFS_SID_BASE_SIZE,
1122+
sizeof(__le32) * (size_t)(*sid)->num_subauth,
1123+
&sid_end))
1124+
return -EINVAL;
1125+
1126+
if (sid_offset > pntsd_size || sid_end > pntsd_size - sid_offset)
1127+
return -EINVAL;
1128+
1129+
*sid_size = sid_end;
1130+
return 0;
1131+
}
1132+
10991133
int smb_inherit_dacl(struct ksmbd_conn *conn,
11001134
const struct path *path,
11011135
unsigned int uid, unsigned int gid)
@@ -1108,28 +1142,28 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
11081142
struct dentry *parent = path->dentry->d_parent;
11091143
struct mnt_idmap *idmap = mnt_idmap(path->mnt);
11101144
int inherited_flags = 0, flags = 0, i, nt_size = 0, pdacl_size;
1111-
int rc = 0, pntsd_type, pntsd_size, acl_len, aces_size;
1145+
int rc = 0, pntsd_type, ppntsd_size, acl_len, aces_size;
11121146
unsigned int dacloffset;
11131147
size_t dacl_struct_end;
11141148
u16 num_aces, ace_cnt = 0;
11151149
char *aces_base;
11161150
bool is_dir = S_ISDIR(d_inode(path->dentry)->i_mode);
11171151

1118-
pntsd_size = ksmbd_vfs_get_sd_xattr(conn, idmap,
1152+
ppntsd_size = ksmbd_vfs_get_sd_xattr(conn, idmap,
11191153
parent, &parent_pntsd);
1120-
if (pntsd_size <= 0)
1154+
if (ppntsd_size <= 0)
11211155
return -ENOENT;
11221156

11231157
dacloffset = le32_to_cpu(parent_pntsd->dacloffset);
11241158
if (!dacloffset ||
11251159
check_add_overflow(dacloffset, sizeof(struct smb_acl), &dacl_struct_end) ||
1126-
dacl_struct_end > (size_t)pntsd_size) {
1160+
dacl_struct_end > (size_t)ppntsd_size) {
11271161
rc = -EINVAL;
11281162
goto free_parent_pntsd;
11291163
}
11301164

11311165
parent_pdacl = (struct smb_acl *)((char *)parent_pntsd + dacloffset);
1132-
acl_len = pntsd_size - dacloffset;
1166+
acl_len = ppntsd_size - dacloffset;
11331167
num_aces = le16_to_cpu(parent_pdacl->num_aces);
11341168
pntsd_type = le16_to_cpu(parent_pntsd->type);
11351169
pdacl_size = le16_to_cpu(parent_pdacl->size);
@@ -1243,19 +1277,19 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
12431277
struct smb_ntsd *pntsd;
12441278
struct smb_acl *pdacl;
12451279
struct smb_sid *powner_sid = NULL, *pgroup_sid = NULL;
1246-
int powner_sid_size = 0, pgroup_sid_size = 0, pntsd_size;
1280+
size_t powner_sid_size = 0, pgroup_sid_size = 0, pntsd_size;
12471281
size_t pntsd_alloc_size;
12481282

1249-
if (parent_pntsd->osidoffset) {
1250-
powner_sid = (struct smb_sid *)((char *)parent_pntsd +
1251-
le32_to_cpu(parent_pntsd->osidoffset));
1252-
powner_sid_size = 1 + 1 + 6 + (powner_sid->num_subauth * 4);
1253-
}
1254-
if (parent_pntsd->gsidoffset) {
1255-
pgroup_sid = (struct smb_sid *)((char *)parent_pntsd +
1256-
le32_to_cpu(parent_pntsd->gsidoffset));
1257-
pgroup_sid_size = 1 + 1 + 6 + (pgroup_sid->num_subauth * 4);
1258-
}
1283+
rc = smb_validate_ntsd_sid(parent_pntsd, ppntsd_size,
1284+
le32_to_cpu(parent_pntsd->osidoffset),
1285+
&powner_sid, &powner_sid_size);
1286+
if (rc)
1287+
goto free_aces_base;
1288+
rc = smb_validate_ntsd_sid(parent_pntsd, ppntsd_size,
1289+
le32_to_cpu(parent_pntsd->gsidoffset),
1290+
&pgroup_sid, &pgroup_sid_size);
1291+
if (rc)
1292+
goto free_aces_base;
12591293

12601294
if (check_add_overflow(sizeof(struct smb_ntsd),
12611295
(size_t)powner_sid_size,

0 commit comments

Comments
 (0)