Skip to content

Commit e5cf61f

Browse files
committed
Merge tag 'v6.17-rc-smb3-server-fixes' of git://git.samba.org/ksmbd
Pull smb server updates from Steve French: - Fix mtime/ctime reporting issue - Auth fixes, including two session setup race bugs reported by ZDI - Locking improvement in query directory - Fix for potential deadlock in creating hardlinks - Improvements to path name processing * tag 'v6.17-rc-smb3-server-fixes' of git://git.samba.org/ksmbd: ksmbd: fix corrupted mtime and ctime in smb2_open ksmbd: fix Preauh_HashValue race condition ksmbd: check return value of xa_store() in krb5_authenticate ksmbd: fix null pointer dereference error in generate_encryptionkey smb/server: add ksmbd_vfs_kern_path() smb/server: avoid deadlock when linking with ReplaceIfExists smb/server: simplify ksmbd_vfs_kern_path_locked() smb/server: use lookup_one_unlocked()
2 parents cb6bbff + 4f8ff94 commit e5cf61f

File tree

3 files changed

+174
-164
lines changed

3 files changed

+174
-164
lines changed

fs/smb/server/smb2pdu.c

Lines changed: 41 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,7 +1594,7 @@ static int krb5_authenticate(struct ksmbd_work *work,
15941594
struct ksmbd_conn *conn = work->conn;
15951595
struct ksmbd_session *sess = work->sess;
15961596
char *in_blob, *out_blob;
1597-
struct channel *chann = NULL;
1597+
struct channel *chann = NULL, *old;
15981598
u64 prev_sess_id;
15991599
int in_len, out_len;
16001600
int retval;
@@ -1621,11 +1621,24 @@ static int krb5_authenticate(struct ksmbd_work *work,
16211621

16221622
rsp->SecurityBufferLength = cpu_to_le16(out_len);
16231623

1624-
if ((conn->sign || server_conf.enforced_signing) ||
1624+
/*
1625+
* If session state is SMB2_SESSION_VALID, We can assume
1626+
* that it is reauthentication. And the user/password
1627+
* has been verified, so return it here.
1628+
*/
1629+
if (sess->state == SMB2_SESSION_VALID) {
1630+
if (conn->binding)
1631+
goto binding_session;
1632+
return 0;
1633+
}
1634+
1635+
if ((rsp->SessionFlags != SMB2_SESSION_FLAG_IS_GUEST_LE &&
1636+
(conn->sign || server_conf.enforced_signing)) ||
16251637
(req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
16261638
sess->sign = true;
16271639

1628-
if (smb3_encryption_negotiated(conn)) {
1640+
if (smb3_encryption_negotiated(conn) &&
1641+
!(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
16291642
retval = conn->ops->generate_encryptionkey(conn, sess);
16301643
if (retval) {
16311644
ksmbd_debug(SMB,
@@ -1638,6 +1651,7 @@ static int krb5_authenticate(struct ksmbd_work *work,
16381651
sess->sign = false;
16391652
}
16401653

1654+
binding_session:
16411655
if (conn->dialect >= SMB30_PROT_ID) {
16421656
chann = lookup_chann_list(sess, conn);
16431657
if (!chann) {
@@ -1646,7 +1660,12 @@ static int krb5_authenticate(struct ksmbd_work *work,
16461660
return -ENOMEM;
16471661

16481662
chann->conn = conn;
1649-
xa_store(&sess->ksmbd_chann_list, (long)conn, chann, KSMBD_DEFAULT_GFP);
1663+
old = xa_store(&sess->ksmbd_chann_list, (long)conn,
1664+
chann, KSMBD_DEFAULT_GFP);
1665+
if (xa_is_err(old)) {
1666+
kfree(chann);
1667+
return xa_err(old);
1668+
}
16501669
}
16511670
}
16521671

@@ -1833,8 +1852,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
18331852
ksmbd_conn_set_good(conn);
18341853
sess->state = SMB2_SESSION_VALID;
18351854
}
1836-
kfree(sess->Preauth_HashValue);
1837-
sess->Preauth_HashValue = NULL;
18381855
} else if (conn->preferred_auth_mech == KSMBD_AUTH_NTLMSSP) {
18391856
if (negblob->MessageType == NtLmNegotiate) {
18401857
rc = ntlm_negotiate(work, negblob, negblob_len, rsp);
@@ -1861,8 +1878,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
18611878
kfree(preauth_sess);
18621879
}
18631880
}
1864-
kfree(sess->Preauth_HashValue);
1865-
sess->Preauth_HashValue = NULL;
18661881
} else {
18671882
pr_info_ratelimited("Unknown NTLMSSP message type : 0x%x\n",
18681883
le32_to_cpu(negblob->MessageType));
@@ -2581,7 +2596,7 @@ static void smb2_update_xattrs(struct ksmbd_tree_connect *tcon,
25812596
}
25822597
}
25832598

2584-
static int smb2_creat(struct ksmbd_work *work, struct path *parent_path,
2599+
static int smb2_creat(struct ksmbd_work *work,
25852600
struct path *path, char *name, int open_flags,
25862601
umode_t posix_mode, bool is_dir)
25872602
{
@@ -2610,7 +2625,7 @@ static int smb2_creat(struct ksmbd_work *work, struct path *parent_path,
26102625
return rc;
26112626
}
26122627

2613-
rc = ksmbd_vfs_kern_path_locked(work, name, 0, parent_path, path, 0);
2628+
rc = ksmbd_vfs_kern_path(work, name, 0, path, 0);
26142629
if (rc) {
26152630
pr_err("cannot get linux path (%s), err = %d\n",
26162631
name, rc);
@@ -2860,7 +2875,7 @@ int smb2_open(struct ksmbd_work *work)
28602875
struct ksmbd_tree_connect *tcon = work->tcon;
28612876
struct smb2_create_req *req;
28622877
struct smb2_create_rsp *rsp;
2863-
struct path path, parent_path;
2878+
struct path path;
28642879
struct ksmbd_share_config *share = tcon->share_conf;
28652880
struct ksmbd_file *fp = NULL;
28662881
struct file *filp = NULL;
@@ -3116,8 +3131,8 @@ int smb2_open(struct ksmbd_work *work)
31163131
goto err_out2;
31173132
}
31183133

3119-
rc = ksmbd_vfs_kern_path_locked(work, name, LOOKUP_NO_SYMLINKS,
3120-
&parent_path, &path, 1);
3134+
rc = ksmbd_vfs_kern_path(work, name, LOOKUP_NO_SYMLINKS,
3135+
&path, 1);
31213136
if (!rc) {
31223137
file_present = true;
31233138

@@ -3238,7 +3253,7 @@ int smb2_open(struct ksmbd_work *work)
32383253

32393254
/*create file if not present */
32403255
if (!file_present) {
3241-
rc = smb2_creat(work, &parent_path, &path, name, open_flags,
3256+
rc = smb2_creat(work, &path, name, open_flags,
32423257
posix_mode,
32433258
req->CreateOptions & FILE_DIRECTORY_FILE_LE);
32443259
if (rc) {
@@ -3443,7 +3458,7 @@ int smb2_open(struct ksmbd_work *work)
34433458
}
34443459

34453460
if (file_present || created)
3446-
ksmbd_vfs_kern_path_unlock(&parent_path, &path);
3461+
path_put(&path);
34473462

34483463
if (!S_ISDIR(file_inode(filp)->i_mode) && open_flags & O_TRUNC &&
34493464
!fp->attrib_only && !stream_name) {
@@ -3724,7 +3739,7 @@ int smb2_open(struct ksmbd_work *work)
37243739

37253740
err_out:
37263741
if (rc && (file_present || created))
3727-
ksmbd_vfs_kern_path_unlock(&parent_path, &path);
3742+
path_put(&path);
37283743

37293744
err_out1:
37303745
ksmbd_revert_fsids(work);
@@ -4108,20 +4123,6 @@ struct smb2_query_dir_private {
41084123
int info_level;
41094124
};
41104125

4111-
static void lock_dir(struct ksmbd_file *dir_fp)
4112-
{
4113-
struct dentry *dir = dir_fp->filp->f_path.dentry;
4114-
4115-
inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
4116-
}
4117-
4118-
static void unlock_dir(struct ksmbd_file *dir_fp)
4119-
{
4120-
struct dentry *dir = dir_fp->filp->f_path.dentry;
4121-
4122-
inode_unlock(d_inode(dir));
4123-
}
4124-
41254126
static int process_query_dir_entries(struct smb2_query_dir_private *priv)
41264127
{
41274128
struct mnt_idmap *idmap = file_mnt_idmap(priv->dir_fp->filp);
@@ -4136,12 +4137,10 @@ static int process_query_dir_entries(struct smb2_query_dir_private *priv)
41364137
if (dentry_name(priv->d_info, priv->info_level))
41374138
return -EINVAL;
41384139

4139-
lock_dir(priv->dir_fp);
4140-
dent = lookup_one(idmap,
4141-
&QSTR_LEN(priv->d_info->name,
4142-
priv->d_info->name_len),
4143-
priv->dir_fp->filp->f_path.dentry);
4144-
unlock_dir(priv->dir_fp);
4140+
dent = lookup_one_unlocked(idmap,
4141+
&QSTR_LEN(priv->d_info->name,
4142+
priv->d_info->name_len),
4143+
priv->dir_fp->filp->f_path.dentry);
41454144

41464145
if (IS_ERR(dent)) {
41474146
ksmbd_debug(SMB, "Cannot lookup `%s' [%ld]\n",
@@ -6052,8 +6051,7 @@ static int smb2_create_link(struct ksmbd_work *work,
60526051
struct nls_table *local_nls)
60536052
{
60546053
char *link_name = NULL, *target_name = NULL, *pathname = NULL;
6055-
struct path path, parent_path;
6056-
bool file_present = false;
6054+
struct path path;
60576055
int rc;
60586056

60596057
if (buf_len < (u64)sizeof(struct smb2_file_link_info) +
@@ -6082,37 +6080,30 @@ static int smb2_create_link(struct ksmbd_work *work,
60826080

60836081
ksmbd_debug(SMB, "target name is %s\n", target_name);
60846082
rc = ksmbd_vfs_kern_path_locked(work, link_name, LOOKUP_NO_SYMLINKS,
6085-
&parent_path, &path, 0);
6083+
&path, 0);
60866084
if (rc) {
60876085
if (rc != -ENOENT)
60886086
goto out;
6089-
} else
6090-
file_present = true;
6091-
6092-
if (file_info->ReplaceIfExists) {
6093-
if (file_present) {
6087+
} else {
6088+
if (file_info->ReplaceIfExists) {
60946089
rc = ksmbd_vfs_remove_file(work, &path);
60956090
if (rc) {
60966091
rc = -EINVAL;
60976092
ksmbd_debug(SMB, "cannot delete %s\n",
60986093
link_name);
60996094
goto out;
61006095
}
6101-
}
6102-
} else {
6103-
if (file_present) {
6096+
} else {
61046097
rc = -EEXIST;
61056098
ksmbd_debug(SMB, "link already exists\n");
61066099
goto out;
61076100
}
6101+
ksmbd_vfs_kern_path_unlock(&path);
61086102
}
6109-
61106103
rc = ksmbd_vfs_link(work, target_name, link_name);
61116104
if (rc)
61126105
rc = -EINVAL;
61136106
out:
6114-
if (file_present)
6115-
ksmbd_vfs_kern_path_unlock(&parent_path, &path);
61166107

61176108
if (!IS_ERR(link_name))
61186109
kfree(link_name);

0 commit comments

Comments
 (0)