Skip to content

Commit 4cbfe45

Browse files
committed
Merge tag 'v7.1-rc5-ksmbd-server-fixes' of git://git.samba.org/ksmbd
Pull smb server fixes from Steve French: - fix for creating tmpfiles - fix durable reconnect error path - validate SID in security descriptor when inheriting DACL * tag 'v7.1-rc5-ksmbd-server-fixes' of git://git.samba.org/ksmbd: smb/server: promote S_DEL_ON_CLS to S_DEL_PENDING when close ksmbd: validate SID in parent security descriptor during ACL inheritance ksmbd: fix durable reconnect error path file lifetime
2 parents 4005446 + 4ec9c8e commit 4cbfe45

3 files changed

Lines changed: 75 additions & 22 deletions

File tree

fs/smb/server/smb2pdu.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3804,8 +3804,19 @@ int smb2_open(struct ksmbd_work *work)
38043804
ksmbd_debug(SMB, "Error response: %x\n", rsp->hdr.Status);
38053805
}
38063806

3807-
if (dh_info.reconnected)
3808-
ksmbd_put_durable_fd(dh_info.fp);
3807+
if (dh_info.reconnected) {
3808+
/*
3809+
* If reconnect succeeded, fp was republished in the
3810+
* session file table. On a later error, ksmbd_fd_put()
3811+
* above drops the session reference; drop the durable
3812+
* lookup reference through the same session-aware path so
3813+
* final close removes the volatile id before freeing fp.
3814+
*/
3815+
if (rc && fp == dh_info.fp)
3816+
ksmbd_fd_put(work, dh_info.fp);
3817+
else
3818+
ksmbd_put_durable_fd(dh_info.fp);
3819+
}
38093820

38103821
kfree(name);
38113822
kfree(lc);

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,

fs/smb/server/vfs_cache.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ int ksmbd_query_inode_status(struct dentry *dentry)
211211
return ret;
212212

213213
down_read(&ci->m_lock);
214-
if (ci->m_flags & (S_DEL_PENDING | S_DEL_ON_CLS))
214+
if (ci->m_flags & S_DEL_PENDING)
215215
ret = KSMBD_INODE_STATUS_PENDING_DELETE;
216216
else
217217
ret = KSMBD_INODE_STATUS_OK;
@@ -227,7 +227,7 @@ bool ksmbd_inode_pending_delete(struct ksmbd_file *fp)
227227
int ret;
228228

229229
down_read(&ci->m_lock);
230-
ret = (ci->m_flags & (S_DEL_PENDING | S_DEL_ON_CLS));
230+
ret = (ci->m_flags & S_DEL_PENDING);
231231
up_read(&ci->m_lock);
232232

233233
return ret;
@@ -395,12 +395,20 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
395395
}
396396
}
397397

398+
down_write(&ci->m_lock);
399+
/* Promote S_DEL_ON_CLS to S_DEL_PENDING when close */
400+
if (ci->m_flags & S_DEL_ON_CLS) {
401+
ci->m_flags &= ~S_DEL_ON_CLS;
402+
ci->m_flags |= S_DEL_PENDING;
403+
}
404+
up_write(&ci->m_lock);
405+
398406
if (atomic_dec_and_test(&ci->m_count)) {
399407
bool do_unlink = false;
400408

401409
down_write(&ci->m_lock);
402-
if (ci->m_flags & (S_DEL_ON_CLS | S_DEL_PENDING)) {
403-
ci->m_flags &= ~(S_DEL_ON_CLS | S_DEL_PENDING);
410+
if (ci->m_flags & S_DEL_PENDING) {
411+
ci->m_flags &= ~S_DEL_PENDING;
404412
do_unlink = true;
405413
}
406414
up_write(&ci->m_lock);

0 commit comments

Comments
 (0)