Skip to content

Commit f932fb9

Browse files
committed
Merge tag 'v6.13-rc2-ksmbd-server-fixes' of git://git.samba.org/ksmbd
Pull smb server fixes from Steve French: - fix ctime setting in setattr - fix reference count on user session to avoid potential race with session expire - fix query dir issue * tag 'v6.13-rc2-ksmbd-server-fixes' of git://git.samba.org/ksmbd: ksmbd: set ATTR_CTIME flags when setting mtime ksmbd: fix racy issue from session lookup and expire ksmbd: retry iterate_dir in smb2_query_dir
2 parents 01abac2 + 21e46a7 commit f932fb9

File tree

5 files changed

+38
-24
lines changed

5 files changed

+38
-24
lines changed

fs/smb/server/auth.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,8 @@ static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id,
10161016

10171017
ses_enc_key = enc ? sess->smb3encryptionkey :
10181018
sess->smb3decryptionkey;
1019+
if (enc)
1020+
ksmbd_user_session_get(sess);
10191021
memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
10201022

10211023
return 0;

fs/smb/server/mgmt/user_session.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,10 @@ struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
263263

264264
down_read(&conn->session_lock);
265265
sess = xa_load(&conn->sessions, id);
266-
if (sess)
266+
if (sess) {
267267
sess->last_active = jiffies;
268+
ksmbd_user_session_get(sess);
269+
}
268270
up_read(&conn->session_lock);
269271
return sess;
270272
}
@@ -275,6 +277,8 @@ struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id)
275277

276278
down_read(&sessions_table_lock);
277279
sess = __session_lookup(id);
280+
if (sess)
281+
ksmbd_user_session_get(sess);
278282
up_read(&sessions_table_lock);
279283

280284
return sess;

fs/smb/server/server.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,14 +241,14 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
241241
if (work->tcon)
242242
ksmbd_tree_connect_put(work->tcon);
243243
smb3_preauth_hash_rsp(work);
244-
if (work->sess)
245-
ksmbd_user_session_put(work->sess);
246244
if (work->sess && work->sess->enc && work->encrypted &&
247245
conn->ops->encrypt_resp) {
248246
rc = conn->ops->encrypt_resp(work);
249247
if (rc < 0)
250248
conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
251249
}
250+
if (work->sess)
251+
ksmbd_user_session_put(work->sess);
252252

253253
ksmbd_conn_write(work);
254254
}

fs/smb/server/smb2pdu.c

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,10 @@ static inline bool check_session_id(struct ksmbd_conn *conn, u64 id)
6767
return false;
6868

6969
sess = ksmbd_session_lookup_all(conn, id);
70-
if (sess)
70+
if (sess) {
71+
ksmbd_user_session_put(sess);
7172
return true;
73+
}
7274
pr_err("Invalid user session id: %llu\n", id);
7375
return false;
7476
}
@@ -605,10 +607,8 @@ int smb2_check_user_session(struct ksmbd_work *work)
605607

606608
/* Check for validity of user session */
607609
work->sess = ksmbd_session_lookup_all(conn, sess_id);
608-
if (work->sess) {
609-
ksmbd_user_session_get(work->sess);
610+
if (work->sess)
610611
return 1;
611-
}
612612
ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id);
613613
return -ENOENT;
614614
}
@@ -1701,37 +1701,44 @@ int smb2_sess_setup(struct ksmbd_work *work)
17011701

17021702
if (conn->dialect != sess->dialect) {
17031703
rc = -EINVAL;
1704+
ksmbd_user_session_put(sess);
17041705
goto out_err;
17051706
}
17061707

17071708
if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) {
17081709
rc = -EINVAL;
1710+
ksmbd_user_session_put(sess);
17091711
goto out_err;
17101712
}
17111713

17121714
if (strncmp(conn->ClientGUID, sess->ClientGUID,
17131715
SMB2_CLIENT_GUID_SIZE)) {
17141716
rc = -ENOENT;
1717+
ksmbd_user_session_put(sess);
17151718
goto out_err;
17161719
}
17171720

17181721
if (sess->state == SMB2_SESSION_IN_PROGRESS) {
17191722
rc = -EACCES;
1723+
ksmbd_user_session_put(sess);
17201724
goto out_err;
17211725
}
17221726

17231727
if (sess->state == SMB2_SESSION_EXPIRED) {
17241728
rc = -EFAULT;
1729+
ksmbd_user_session_put(sess);
17251730
goto out_err;
17261731
}
1732+
ksmbd_user_session_put(sess);
17271733

17281734
if (ksmbd_conn_need_reconnect(conn)) {
17291735
rc = -EFAULT;
17301736
sess = NULL;
17311737
goto out_err;
17321738
}
17331739

1734-
if (ksmbd_session_lookup(conn, sess_id)) {
1740+
sess = ksmbd_session_lookup(conn, sess_id);
1741+
if (!sess) {
17351742
rc = -EACCES;
17361743
goto out_err;
17371744
}
@@ -1742,7 +1749,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
17421749
}
17431750

17441751
conn->binding = true;
1745-
ksmbd_user_session_get(sess);
17461752
} else if ((conn->dialect < SMB30_PROT_ID ||
17471753
server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
17481754
(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
@@ -1769,7 +1775,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
17691775
}
17701776

17711777
conn->binding = false;
1772-
ksmbd_user_session_get(sess);
17731778
}
17741779
work->sess = sess;
17751780

@@ -2197,9 +2202,9 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
21972202
int smb2_session_logoff(struct ksmbd_work *work)
21982203
{
21992204
struct ksmbd_conn *conn = work->conn;
2205+
struct ksmbd_session *sess = work->sess;
22002206
struct smb2_logoff_req *req;
22012207
struct smb2_logoff_rsp *rsp;
2202-
struct ksmbd_session *sess;
22032208
u64 sess_id;
22042209
int err;
22052210

@@ -2221,11 +2226,6 @@ int smb2_session_logoff(struct ksmbd_work *work)
22212226
ksmbd_close_session_fds(work);
22222227
ksmbd_conn_wait_idle(conn);
22232228

2224-
/*
2225-
* Re-lookup session to validate if session is deleted
2226-
* while waiting request complete
2227-
*/
2228-
sess = ksmbd_session_lookup_all(conn, sess_id);
22292229
if (ksmbd_tree_conn_session_logoff(sess)) {
22302230
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
22312231
rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
@@ -4228,6 +4228,7 @@ static bool __query_dir(struct dir_context *ctx, const char *name, int namlen,
42284228
/* dot and dotdot entries are already reserved */
42294229
if (!strcmp(".", name) || !strcmp("..", name))
42304230
return true;
4231+
d_info->num_scan++;
42314232
if (ksmbd_share_veto_filename(priv->work->tcon->share_conf, name))
42324233
return true;
42334234
if (!match_pattern(name, namlen, priv->search_pattern))
@@ -4390,8 +4391,17 @@ int smb2_query_dir(struct ksmbd_work *work)
43904391
query_dir_private.info_level = req->FileInformationClass;
43914392
dir_fp->readdir_data.private = &query_dir_private;
43924393
set_ctx_actor(&dir_fp->readdir_data.ctx, __query_dir);
4393-
4394+
again:
4395+
d_info.num_scan = 0;
43944396
rc = iterate_dir(dir_fp->filp, &dir_fp->readdir_data.ctx);
4397+
/*
4398+
* num_entry can be 0 if the directory iteration stops before reaching
4399+
* the end of the directory and no file is matched with the search
4400+
* pattern.
4401+
*/
4402+
if (rc >= 0 && !d_info.num_entry && d_info.num_scan &&
4403+
d_info.out_buf_len > 0)
4404+
goto again;
43954405
/*
43964406
* req->OutputBufferLength is too small to contain even one entry.
43974407
* In this case, it immediately returns OutputBufferLength 0 to client.
@@ -6016,15 +6026,13 @@ static int set_file_basic_info(struct ksmbd_file *fp,
60166026
attrs.ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
60176027
}
60186028

6019-
attrs.ia_valid |= ATTR_CTIME;
60206029
if (file_info->ChangeTime)
6021-
attrs.ia_ctime = ksmbd_NTtimeToUnix(file_info->ChangeTime);
6022-
else
6023-
attrs.ia_ctime = inode_get_ctime(inode);
6030+
inode_set_ctime_to_ts(inode,
6031+
ksmbd_NTtimeToUnix(file_info->ChangeTime));
60246032

60256033
if (file_info->LastWriteTime) {
60266034
attrs.ia_mtime = ksmbd_NTtimeToUnix(file_info->LastWriteTime);
6027-
attrs.ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
6035+
attrs.ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET | ATTR_CTIME);
60286036
}
60296037

60306038
if (file_info->Attributes) {
@@ -6066,8 +6074,6 @@ static int set_file_basic_info(struct ksmbd_file *fp,
60666074
return -EACCES;
60676075

60686076
inode_lock(inode);
6069-
inode_set_ctime_to_ts(inode, attrs.ia_ctime);
6070-
attrs.ia_valid &= ~ATTR_CTIME;
60716077
rc = notify_change(idmap, dentry, &attrs, NULL);
60726078
inode_unlock(inode);
60736079
}
@@ -8982,6 +8988,7 @@ int smb3_decrypt_req(struct ksmbd_work *work)
89828988
le64_to_cpu(tr_hdr->SessionId));
89838989
return -ECONNABORTED;
89848990
}
8991+
ksmbd_user_session_put(sess);
89858992

89868993
iov[0].iov_base = buf;
89878994
iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;

fs/smb/server/vfs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ struct ksmbd_dir_info {
4343
char *rptr;
4444
int name_len;
4545
int out_buf_len;
46+
int num_scan;
4647
int num_entry;
4748
int data_count;
4849
int last_entry_offset;

0 commit comments

Comments
 (0)