1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2018 Samsung Electronics Co., Ltd.
4 */
5
6 #include <linux/list.h>
7 #include <linux/slab.h>
8 #include <linux/rwsem.h>
9 #include <linux/xarray.h>
10
11 #include "ksmbd_ida.h"
12 #include "user_session.h"
13 #include "user_config.h"
14 #include "tree_connect.h"
15 #include "share_config.h"
16 #include "../transport_ipc.h"
17 #include "../connection.h"
18 #include "../vfs_cache.h"
19 #include "../misc.h"
20 #include "../stats.h"
21
22 static DEFINE_IDA(session_ida);
23
24 #define SESSION_HASH_BITS 12
25 #define KSMBD_MAX_PENDING_SESSIONS 1
26 static DEFINE_HASHTABLE(sessions_table, SESSION_HASH_BITS);
27 static DECLARE_RWSEM(sessions_table_lock);
28
29 struct ksmbd_session_rpc {
30 int id;
31 unsigned int method;
32 };
33
34 #ifdef CONFIG_PROC_FS
35
36 static const struct ksmbd_const_name ksmbd_sess_cap_const_names[] = {
37 {SMB2_GLOBAL_CAP_DFS, "dfs"},
38 {SMB2_GLOBAL_CAP_LEASING, "lease"},
39 {SMB2_GLOBAL_CAP_LARGE_MTU, "large-mtu"},
40 {SMB2_GLOBAL_CAP_MULTI_CHANNEL, "multi-channel"},
41 {SMB2_GLOBAL_CAP_PERSISTENT_HANDLES, "persistent-handles"},
42 {SMB2_GLOBAL_CAP_DIRECTORY_LEASING, "dir-lease"},
43 {SMB2_GLOBAL_CAP_ENCRYPTION, "encryption"}
44 };
45
46 static const struct ksmbd_const_name ksmbd_cipher_const_names[] = {
47 {le16_to_cpu(SMB2_ENCRYPTION_AES128_CCM), "aes128-ccm"},
48 {le16_to_cpu(SMB2_ENCRYPTION_AES128_GCM), "aes128-gcm"},
49 {le16_to_cpu(SMB2_ENCRYPTION_AES256_CCM), "aes256-ccm"},
50 {le16_to_cpu(SMB2_ENCRYPTION_AES256_GCM), "aes256-gcm"},
51 };
52
53 static const struct ksmbd_const_name ksmbd_signing_const_names[] = {
54 {SIGNING_ALG_HMAC_SHA256, "hmac-sha256"},
55 {SIGNING_ALG_AES_CMAC, "aes-cmac"},
56 {SIGNING_ALG_AES_GMAC, "aes-gmac"},
57 };
58
session_state_string(struct ksmbd_session * session)59 static const char *session_state_string(struct ksmbd_session *session)
60 {
61 switch (session->state) {
62 case SMB2_SESSION_VALID:
63 return "valid";
64 case SMB2_SESSION_IN_PROGRESS:
65 return "progress";
66 case SMB2_SESSION_EXPIRED:
67 return "expired";
68 default:
69 return "";
70 }
71 }
72
session_user_name(struct ksmbd_session * session)73 static const char *session_user_name(struct ksmbd_session *session)
74 {
75 if (user_guest(session->user))
76 return "(Guest)";
77 else if (ksmbd_anonymous_user(session->user))
78 return "(Anonymous)";
79 return session->user->name;
80 }
81
session_account_type(struct ksmbd_session * session)82 static const char *session_account_type(struct ksmbd_session *session)
83 {
84 if (user_guest(session->user))
85 return "guest";
86 if (ksmbd_anonymous_user(session->user))
87 return "anonymous";
88 return "user";
89 }
90
session_open_file_count(struct ksmbd_session * session)91 static unsigned int session_open_file_count(struct ksmbd_session *session)
92 {
93 struct ksmbd_file *fp;
94 unsigned int count = 0;
95 unsigned int id;
96
97 read_lock(&session->file_table.lock);
98 idr_for_each_entry(session->file_table.idr, fp, id)
99 count++;
100 read_unlock(&session->file_table.lock);
101 return count;
102 }
103
show_proc_session(struct seq_file * m,void * v)104 static int show_proc_session(struct seq_file *m, void *v)
105 {
106 struct ksmbd_session *sess;
107 struct ksmbd_tree_connect *tree_conn;
108 struct ksmbd_share_config *share_conf;
109 struct channel *chan;
110 unsigned long id;
111 int i = 0;
112
113 sess = (struct ksmbd_session *)m->private;
114 ksmbd_user_session_get(sess);
115
116 seq_printf(m, "user:\t%s\n", session_user_name(sess));
117 seq_printf(m, "account_type:\t%s\n",
118 session_account_type(sess));
119 seq_printf(m, "id:\t%llu\n", sess->id);
120 seq_printf(m, "state:\t%s\n", session_state_string(sess));
121 seq_printf(m, "dialect:\t0x%04x\n", sess->dialect);
122 seq_printf(m, "last_active_seconds:\t%lu\n",
123 jiffies_to_msecs(jiffies - sess->last_active) / MSEC_PER_SEC);
124 seq_printf(m, "open_files:\t%u\n",
125 session_open_file_count(sess));
126
127 i = 0;
128 down_read(&sess->chann_lock);
129 xa_for_each(&sess->ksmbd_chann_list, id, chan) {
130 const char *name;
131
132 #if IS_ENABLED(CONFIG_IPV6)
133 if (chan->conn->inet_addr)
134 seq_printf(m, "client:\t%pI4\n",
135 &chan->conn->inet_addr);
136 else
137 seq_printf(m, "client:\t%pI6c\n",
138 &chan->conn->inet6_addr);
139 #else
140 seq_printf(m, "client:\t%pI4\n",
141 &chan->conn->inet_addr);
142 #endif
143 seq_puts(m, "capabilities:\t");
144 ksmbd_proc_show_flag_names(m,
145 ksmbd_sess_cap_const_names,
146 ARRAY_SIZE(ksmbd_sess_cap_const_names),
147 chan->conn->vals->req_capabilities);
148 seq_putc(m, '\n');
149 seq_printf(m, "posix_extensions:\t%s\n",
150 chan->conn->posix_ext_supported ? "yes" : "no");
151
152 if (sess->sign) {
153 unsigned int algorithm =
154 le16_to_cpu(chan->conn->signing_algorithm);
155
156 name = ksmbd_proc_const_name(ksmbd_signing_const_names,
157 ARRAY_SIZE(ksmbd_signing_const_names),
158 algorithm);
159 if (name)
160 seq_printf(m, "signing:\t%s\n", name);
161 else
162 seq_printf(m, "signing:\t0x%04x\n",
163 algorithm);
164 }
165 if (sess->enc) {
166 unsigned int cipher = le16_to_cpu(chan->conn->cipher_type);
167
168 name = ksmbd_proc_const_name(ksmbd_cipher_const_names,
169 ARRAY_SIZE(ksmbd_cipher_const_names),
170 cipher);
171 if (name)
172 seq_printf(m, "encryption:\t%s\n", name);
173 else
174 seq_printf(m, "encryption:\t0x%04x\n",
175 cipher);
176 }
177 i++;
178 }
179 up_read(&sess->chann_lock);
180
181 seq_printf(m, "channels:\t%d\n", i);
182
183 i = 0;
184 down_read(&sess->tree_conns_lock);
185 xa_for_each(&sess->tree_conns, id, tree_conn) {
186 share_conf = tree_conn->share_conf;
187 seq_printf(m, "share:\t%s\n", share_conf->name);
188 seq_printf(m, "tree_id:\t%d\n", tree_conn->id);
189 seq_printf(m, "share_type:\t%s\n",
190 test_share_config_flag(share_conf, KSMBD_SHARE_FLAG_PIPE) ?
191 "pipe" : "disk");
192 i++;
193 }
194 up_read(&sess->tree_conns_lock);
195 seq_printf(m, "tree_connects:\t%d\n", i);
196
197 ksmbd_user_session_put(sess);
198 return 0;
199 }
200
create_proc_session(struct ksmbd_session * sess)201 static int create_proc_session(struct ksmbd_session *sess)
202 {
203 char name[30];
204
205 snprintf(name, sizeof(name), "sessions/%llu", sess->id);
206 sess->proc_entry = ksmbd_proc_create(name,
207 show_proc_session, sess);
208 if (!sess->proc_entry)
209 return -ENOMEM;
210 return 0;
211 }
212
delete_proc_session(struct ksmbd_session * sess)213 static void delete_proc_session(struct ksmbd_session *sess)
214 {
215 if (sess->proc_entry)
216 proc_remove(sess->proc_entry);
217 }
218
show_proc_sessions(struct seq_file * m,void * v)219 static int show_proc_sessions(struct seq_file *m, void *v)
220 {
221 struct ksmbd_session *session;
222 struct channel *chan;
223 int i;
224 unsigned long id;
225
226 down_read(&sessions_table_lock);
227 hash_for_each(sessions_table, i, session, hlist) {
228 down_read(&session->chann_lock);
229 xa_for_each(&session->ksmbd_chann_list, id, chan) {
230 down_read(&chan->conn->session_lock);
231 ksmbd_user_session_get(session);
232
233 #if IS_ENABLED(CONFIG_IPV6)
234 if (!chan->conn->inet_addr)
235 seq_printf(m, "client:\t%pI6c\n", &chan->conn->inet6_addr);
236 else
237 #endif
238 seq_printf(m, "client:\t%pI4\n", &chan->conn->inet_addr);
239 seq_printf(m, "user:\t%s\n", session_user_name(session));
240 seq_printf(m, "id:\t%llu\n", session->id);
241 seq_printf(m, "state:\t%s\n\n",
242 session_state_string(session));
243
244 ksmbd_user_session_put(session);
245 up_read(&chan->conn->session_lock);
246 }
247 up_read(&session->chann_lock);
248 }
249 up_read(&sessions_table_lock);
250 return 0;
251 }
252
create_proc_sessions(void)253 int create_proc_sessions(void)
254 {
255 if (!ksmbd_proc_create("sessions/sessions",
256 show_proc_sessions, NULL))
257 return -ENOMEM;
258 return 0;
259 }
260 #else
create_proc_sessions(void)261 int create_proc_sessions(void) { return 0; }
create_proc_session(struct ksmbd_session * sess)262 static int create_proc_session(struct ksmbd_session *sess) { return 0; }
delete_proc_session(struct ksmbd_session * sess)263 static void delete_proc_session(struct ksmbd_session *sess) {}
264 #endif
265
free_channel_list(struct ksmbd_session * sess)266 static void free_channel_list(struct ksmbd_session *sess)
267 {
268 struct channel *chann;
269 unsigned long index;
270
271 down_write(&sess->chann_lock);
272 xa_for_each(&sess->ksmbd_chann_list, index, chann) {
273 xa_erase(&sess->ksmbd_chann_list, index);
274 kfree_sensitive(chann);
275 }
276
277 xa_destroy(&sess->ksmbd_chann_list);
278 up_write(&sess->chann_lock);
279 }
280
__session_rpc_close(struct ksmbd_session * sess,struct ksmbd_session_rpc * entry)281 static void __session_rpc_close(struct ksmbd_session *sess,
282 struct ksmbd_session_rpc *entry)
283 {
284 struct ksmbd_rpc_command *resp;
285
286 resp = ksmbd_rpc_close(sess, entry->id);
287 if (!resp)
288 pr_err("Unable to close RPC pipe %d\n", entry->id);
289
290 kvfree(resp);
291 ksmbd_rpc_id_free(entry->id);
292 kfree(entry);
293 }
294
ksmbd_session_rpc_clear_list(struct ksmbd_session * sess)295 static void ksmbd_session_rpc_clear_list(struct ksmbd_session *sess)
296 {
297 struct ksmbd_session_rpc *entry;
298 long index;
299
300 down_write(&sess->rpc_lock);
301 xa_for_each(&sess->rpc_handle_list, index, entry) {
302 xa_erase(&sess->rpc_handle_list, index);
303 __session_rpc_close(sess, entry);
304 }
305 up_write(&sess->rpc_lock);
306
307 xa_destroy(&sess->rpc_handle_list);
308 }
309
__rpc_method(char * rpc_name)310 static int __rpc_method(char *rpc_name)
311 {
312 if (!strcmp(rpc_name, "\\srvsvc") || !strcmp(rpc_name, "srvsvc"))
313 return KSMBD_RPC_SRVSVC_METHOD_INVOKE;
314
315 if (!strcmp(rpc_name, "\\wkssvc") || !strcmp(rpc_name, "wkssvc"))
316 return KSMBD_RPC_WKSSVC_METHOD_INVOKE;
317
318 if (!strcmp(rpc_name, "LANMAN") || !strcmp(rpc_name, "lanman"))
319 return KSMBD_RPC_RAP_METHOD;
320
321 if (!strcmp(rpc_name, "\\samr") || !strcmp(rpc_name, "samr"))
322 return KSMBD_RPC_SAMR_METHOD_INVOKE;
323
324 if (!strcmp(rpc_name, "\\lsarpc") || !strcmp(rpc_name, "lsarpc"))
325 return KSMBD_RPC_LSARPC_METHOD_INVOKE;
326
327 if (!strcmp(rpc_name, "\\mdssvc") || !strcmp(rpc_name, "mdssvc"))
328 return -ENOENT;
329
330 pr_err("Unsupported RPC: %s\n", rpc_name);
331 return -ENOENT;
332 }
333
ksmbd_session_rpc_open(struct ksmbd_session * sess,char * rpc_name)334 int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
335 {
336 struct ksmbd_session_rpc *entry, *old;
337 struct ksmbd_rpc_command *resp;
338 int method, id;
339
340 method = __rpc_method(rpc_name);
341 if (method < 0)
342 return method;
343
344 entry = kzalloc_obj(struct ksmbd_session_rpc, KSMBD_DEFAULT_GFP);
345 if (!entry)
346 return -ENOMEM;
347
348 entry->method = method;
349 entry->id = id = ksmbd_ipc_id_alloc();
350 if (id < 0)
351 goto free_entry;
352
353 down_write(&sess->rpc_lock);
354 old = xa_store(&sess->rpc_handle_list, id, entry, KSMBD_DEFAULT_GFP);
355 if (xa_is_err(old)) {
356 up_write(&sess->rpc_lock);
357 goto free_id;
358 }
359
360 resp = ksmbd_rpc_open(sess, id);
361 if (!resp) {
362 xa_erase(&sess->rpc_handle_list, entry->id);
363 up_write(&sess->rpc_lock);
364 goto free_id;
365 }
366
367 up_write(&sess->rpc_lock);
368 kvfree(resp);
369 return id;
370 free_id:
371 ksmbd_rpc_id_free(entry->id);
372 free_entry:
373 kfree(entry);
374 return -EINVAL;
375 }
376
ksmbd_session_rpc_close(struct ksmbd_session * sess,int id)377 void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id)
378 {
379 struct ksmbd_session_rpc *entry;
380
381 down_write(&sess->rpc_lock);
382 entry = xa_erase(&sess->rpc_handle_list, id);
383 if (entry)
384 __session_rpc_close(sess, entry);
385 up_write(&sess->rpc_lock);
386 }
387
ksmbd_session_rpc_method(struct ksmbd_session * sess,int id)388 int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id)
389 {
390 struct ksmbd_session_rpc *entry;
391
392 lockdep_assert_held(&sess->rpc_lock);
393 entry = xa_load(&sess->rpc_handle_list, id);
394
395 return entry ? entry->method : 0;
396 }
397
ksmbd_session_destroy(struct ksmbd_session * sess)398 void ksmbd_session_destroy(struct ksmbd_session *sess)
399 {
400 if (!sess)
401 return;
402
403 delete_proc_session(sess);
404 ksmbd_tree_conn_session_logoff(sess);
405 ksmbd_destroy_file_table(sess);
406 if (sess->user)
407 ksmbd_free_user(sess->user);
408 ksmbd_launch_ksmbd_durable_scavenger();
409 ksmbd_session_rpc_clear_list(sess);
410 free_channel_list(sess);
411 kfree_sensitive(sess->Preauth_HashValue);
412 ksmbd_release_id(&session_ida, sess->id);
413 ida_destroy(&sess->tree_conn_ida);
414 kfree_sensitive(sess);
415 }
416
ksmbd_session_remove_from_table(struct ksmbd_session * sess)417 static void ksmbd_session_remove_from_table(struct ksmbd_session *sess)
418 {
419 hash_del(&sess->hlist);
420 ksmbd_counter_dec(KSMBD_COUNTER_SESSIONS);
421 }
422
__session_lookup(unsigned long long id)423 struct ksmbd_session *__session_lookup(unsigned long long id)
424 {
425 struct ksmbd_session *sess;
426
427 hash_for_each_possible(sessions_table, sess, hlist, id) {
428 if (id == sess->id) {
429 sess->last_active = jiffies;
430 return sess;
431 }
432 }
433 return NULL;
434 }
435
ksmbd_too_many_session_setups(struct ksmbd_conn * conn)436 static bool ksmbd_too_many_session_setups(struct ksmbd_conn *conn)
437 {
438 unsigned long id;
439 struct ksmbd_session *sess;
440 unsigned int pending = 0;
441
442 down_write(&sessions_table_lock);
443 down_write(&conn->session_lock);
444 xa_for_each(&conn->sessions, id, sess) {
445 if (READ_ONCE(sess->state) != SMB2_SESSION_IN_PROGRESS)
446 continue;
447
448 if (atomic_read(&sess->refcnt) <= 1 &&
449 time_after(jiffies, sess->last_active +
450 KSMBD_UNAUTHENTICATED_CONN_TIMEOUT)) {
451 xa_erase(&conn->sessions, sess->id);
452 ksmbd_session_remove_from_table(sess);
453 ksmbd_session_destroy(sess);
454 continue;
455 }
456 pending++;
457 }
458 up_write(&conn->session_lock);
459 up_write(&sessions_table_lock);
460 return pending >= KSMBD_MAX_PENDING_SESSIONS;
461 }
462
ksmbd_session_register(struct ksmbd_conn * conn,struct ksmbd_session * sess)463 int ksmbd_session_register(struct ksmbd_conn *conn,
464 struct ksmbd_session *sess)
465 {
466 int ret;
467
468 sess->dialect = conn->dialect;
469 memcpy(sess->ClientGUID, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
470 /* Bound abandoned SessionId-zero authentication exchanges. */
471 if (ksmbd_too_many_session_setups(conn))
472 ret = -ENOSPC;
473 else
474 ret = xa_err(xa_store(&conn->sessions, sess->id, sess,
475 KSMBD_DEFAULT_GFP));
476 if (ret) {
477 down_write(&sessions_table_lock);
478 ksmbd_session_remove_from_table(sess);
479 up_write(&sessions_table_lock);
480 ksmbd_user_session_put(sess);
481 }
482
483 return ret;
484 }
485
ksmbd_session_unregister(struct ksmbd_conn * conn,struct ksmbd_session * sess)486 void ksmbd_session_unregister(struct ksmbd_conn *conn,
487 struct ksmbd_session *sess)
488 {
489 struct ksmbd_conn *session_conns[KSMBD_MAX_CHANNELS];
490 struct channel *chann;
491 unsigned long index;
492 unsigned int nr_conns = 0, i;
493 bool removed = false;
494
495 down_write(&sessions_table_lock);
496 if (!hlist_unhashed(&sess->hlist)) {
497 /* Keep each channel connection stable under sessions_table_lock. */
498 down_read(&sess->chann_lock);
499 xa_for_each(&sess->ksmbd_chann_list, index, chann) {
500 if (nr_conns == ARRAY_SIZE(session_conns))
501 break;
502 session_conns[nr_conns++] = chann->conn;
503 }
504 up_read(&sess->chann_lock);
505
506 ksmbd_session_remove_from_table(sess);
507 removed = true;
508 }
509
510 down_write(&conn->session_lock);
511 if (xa_load(&conn->sessions, sess->id) == sess)
512 xa_erase(&conn->sessions, sess->id);
513 up_write(&conn->session_lock);
514 for (i = 0; i < nr_conns; i++) {
515 if (session_conns[i] == conn)
516 continue;
517 down_write(&session_conns[i]->session_lock);
518 if (xa_load(&session_conns[i]->sessions, sess->id) == sess)
519 xa_erase(&session_conns[i]->sessions, sess->id);
520 up_write(&session_conns[i]->session_lock);
521 }
522 up_write(&sessions_table_lock);
523
524 if (removed)
525 ksmbd_user_session_put(sess);
526 }
527
ksmbd_conn_has_valid_or_expired_session(struct ksmbd_conn * conn)528 bool ksmbd_conn_has_valid_or_expired_session(struct ksmbd_conn *conn)
529 {
530 struct ksmbd_session *sess;
531 unsigned long id;
532 int state, bkt;
533 bool found = false;
534
535 down_read(&conn->session_lock);
536 xa_for_each(&conn->sessions, id, sess) {
537 state = READ_ONCE(sess->state);
538 if (state == SMB2_SESSION_VALID ||
539 state == SMB2_SESSION_EXPIRED) {
540 found = true;
541 break;
542 }
543 }
544 up_read(&conn->session_lock);
545 if (found)
546 return true;
547
548 /* A session bound through SMB3 multichannel is not in conn->sessions. */
549 down_read(&sessions_table_lock);
550 hash_for_each(sessions_table, bkt, sess, hlist) {
551 state = READ_ONCE(sess->state);
552 if (state != SMB2_SESSION_VALID &&
553 state != SMB2_SESSION_EXPIRED)
554 continue;
555
556 down_read(&sess->chann_lock);
557 found = xa_load(&sess->ksmbd_chann_list, (long)conn);
558 up_read(&sess->chann_lock);
559 if (found)
560 break;
561 }
562 up_read(&sessions_table_lock);
563 return found;
564 }
565
ksmbd_expire_sessions(void)566 void ksmbd_expire_sessions(void)
567 {
568 struct ksmbd_session *sess;
569 u64 now = ktime_get_real_seconds();
570 int bkt;
571
572 down_read(&sessions_table_lock);
573 hash_for_each(sessions_table, bkt, sess, hlist) {
574 if (READ_ONCE(sess->state) != SMB2_SESSION_VALID ||
575 !sess->kerberos_expiry || now < sess->kerberos_expiry)
576 continue;
577
578 if (cmpxchg(&sess->state, SMB2_SESSION_VALID,
579 SMB2_SESSION_EXPIRED) == SMB2_SESSION_VALID)
580 ksmbd_counter_inc(KSMBD_COUNTER_SESSION_TIMEOUTS);
581 }
582 up_read(&sessions_table_lock);
583 }
584
ksmbd_chann_del(struct ksmbd_conn * conn,struct ksmbd_session * sess)585 static int ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess)
586 {
587 struct channel *chann;
588
589 down_write(&sess->chann_lock);
590 chann = xa_erase(&sess->ksmbd_chann_list, (long)conn);
591 up_write(&sess->chann_lock);
592 if (!chann)
593 return -ENOENT;
594
595 kfree_sensitive(chann);
596 return 0;
597 }
598
ksmbd_conn_sessions_cleanup(struct ksmbd_conn * conn)599 void ksmbd_conn_sessions_cleanup(struct ksmbd_conn *conn)
600 {
601 struct ksmbd_session *sess;
602 unsigned long id;
603 struct hlist_node *tmp;
604 int bkt;
605
606 down_write(&sessions_table_lock);
607 hash_for_each_safe(sessions_table, bkt, tmp, sess, hlist) {
608 if (!ksmbd_chann_del(conn, sess) &&
609 xa_empty(&sess->ksmbd_chann_list)) {
610 ksmbd_session_remove_from_table(sess);
611 down_write(&conn->session_lock);
612 xa_erase(&conn->sessions, sess->id);
613 up_write(&conn->session_lock);
614 if (atomic_dec_and_test(&sess->refcnt))
615 ksmbd_session_destroy(sess);
616 }
617 }
618
619 down_write(&conn->session_lock);
620 xa_for_each(&conn->sessions, id, sess) {
621 ksmbd_chann_del(conn, sess);
622 if (xa_empty(&sess->ksmbd_chann_list)) {
623 xa_erase(&conn->sessions, sess->id);
624 ksmbd_session_remove_from_table(sess);
625 if (atomic_dec_and_test(&sess->refcnt))
626 ksmbd_session_destroy(sess);
627 }
628 }
629 up_write(&conn->session_lock);
630 up_write(&sessions_table_lock);
631 }
632
is_ksmbd_session_in_connection(struct ksmbd_conn * conn,unsigned long long id)633 bool is_ksmbd_session_in_connection(struct ksmbd_conn *conn,
634 unsigned long long id)
635 {
636 struct ksmbd_session *sess;
637
638 down_read(&conn->session_lock);
639 sess = xa_load(&conn->sessions, id);
640 if (sess) {
641 up_read(&conn->session_lock);
642 return true;
643 }
644 up_read(&conn->session_lock);
645
646 return false;
647 }
648
ksmbd_session_lookup(struct ksmbd_conn * conn,unsigned long long id)649 struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
650 unsigned long long id)
651 {
652 struct ksmbd_session *sess;
653
654 down_read(&conn->session_lock);
655 sess = xa_load(&conn->sessions, id);
656 if (sess) {
657 sess->last_active = jiffies;
658 ksmbd_user_session_get(sess);
659 }
660 up_read(&conn->session_lock);
661 return sess;
662 }
663
ksmbd_session_lookup_slowpath(unsigned long long id)664 struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id)
665 {
666 struct ksmbd_session *sess;
667
668 down_read(&sessions_table_lock);
669 sess = __session_lookup(id);
670 if (sess)
671 ksmbd_user_session_get(sess);
672 up_read(&sessions_table_lock);
673
674 return sess;
675 }
676
ksmbd_session_lookup_all_states(struct ksmbd_conn * conn,unsigned long long id)677 struct ksmbd_session *ksmbd_session_lookup_all_states(struct ksmbd_conn *conn,
678 unsigned long long id)
679 {
680 struct ksmbd_session *sess;
681 bool channel_found;
682
683 sess = ksmbd_session_lookup(conn, id);
684 if (!sess) {
685 sess = ksmbd_session_lookup_slowpath(id);
686 if (!sess)
687 return NULL;
688
689 down_read(&sess->chann_lock);
690 channel_found = xa_load(&sess->ksmbd_chann_list, (long)conn);
691 up_read(&sess->chann_lock);
692 if (!channel_found) {
693 ksmbd_user_session_put(sess);
694 sess = NULL;
695 }
696 }
697 return sess;
698 }
699
ksmbd_session_lookup_all(struct ksmbd_conn * conn,unsigned long long id)700 struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn,
701 unsigned long long id)
702 {
703 struct ksmbd_session *sess;
704
705 sess = ksmbd_session_lookup_all_states(conn, id);
706 if (sess && sess->state != SMB2_SESSION_VALID) {
707 ksmbd_user_session_put(sess);
708 sess = NULL;
709 }
710 return sess;
711 }
712
ksmbd_user_session_get(struct ksmbd_session * sess)713 void ksmbd_user_session_get(struct ksmbd_session *sess)
714 {
715 atomic_inc(&sess->refcnt);
716 }
717
ksmbd_user_session_put(struct ksmbd_session * sess)718 void ksmbd_user_session_put(struct ksmbd_session *sess)
719 {
720 if (!sess)
721 return;
722
723 if (atomic_read(&sess->refcnt) <= 0)
724 WARN_ON(1);
725 else if (atomic_dec_and_test(&sess->refcnt))
726 ksmbd_session_destroy(sess);
727 }
728
ksmbd_preauth_session_alloc(struct ksmbd_conn * conn,u64 sess_id)729 struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn,
730 u64 sess_id)
731 {
732 struct preauth_session *sess;
733
734 sess = kmalloc_obj(struct preauth_session, KSMBD_DEFAULT_GFP);
735 if (!sess)
736 return NULL;
737
738 sess->id = sess_id;
739 memcpy(sess->Preauth_HashValue, conn->preauth_info->Preauth_HashValue,
740 PREAUTH_HASHVALUE_SIZE);
741 list_add(&sess->preauth_entry, &conn->preauth_sess_table);
742
743 return sess;
744 }
745
ksmbd_preauth_session_destroy(struct ksmbd_conn * conn)746 void ksmbd_preauth_session_destroy(struct ksmbd_conn *conn)
747 {
748 struct preauth_session *sess, *tmp;
749
750 list_for_each_entry_safe(sess, tmp, &conn->preauth_sess_table,
751 preauth_entry) {
752 list_del(&sess->preauth_entry);
753 kfree(sess);
754 }
755 }
756
destroy_previous_session(struct ksmbd_conn * conn,struct ksmbd_user * user,u64 id)757 void destroy_previous_session(struct ksmbd_conn *conn,
758 struct ksmbd_user *user, u64 id)
759 {
760 struct ksmbd_session *prev_sess;
761 struct ksmbd_user *prev_user;
762 int err;
763
764 down_write(&sessions_table_lock);
765 down_write(&conn->session_lock);
766 prev_sess = __session_lookup(id);
767 if (!prev_sess || prev_sess->state == SMB2_SESSION_EXPIRED)
768 goto out;
769
770 prev_user = prev_sess->user;
771 if (!prev_user ||
772 strcmp(user->name, prev_user->name) ||
773 user->passkey_sz != prev_user->passkey_sz ||
774 memcmp(user->passkey, prev_user->passkey, user->passkey_sz))
775 goto out;
776
777 down_write(&prev_sess->chann_lock);
778 if (prev_sess->tearing_down) {
779 up_write(&prev_sess->chann_lock);
780 goto out;
781 }
782 prev_sess->tearing_down = true;
783 up_write(&prev_sess->chann_lock);
784
785 ksmbd_all_conn_set_status(prev_sess, KSMBD_SESS_NEED_RECONNECT);
786 err = ksmbd_conn_wait_idle_sess(conn, prev_sess);
787 if (err) {
788 down_write(&prev_sess->chann_lock);
789 prev_sess->tearing_down = false;
790 up_write(&prev_sess->chann_lock);
791 ksmbd_all_conn_set_status(prev_sess, KSMBD_SESS_GOOD);
792 goto out;
793 }
794
795 ksmbd_destroy_file_table(prev_sess);
796 prev_sess->kerberos_expiry = 0;
797 prev_sess->state = SMB2_SESSION_EXPIRED;
798 ksmbd_all_conn_set_status(prev_sess, KSMBD_SESS_NEED_SETUP);
799 ksmbd_launch_ksmbd_durable_scavenger();
800 out:
801 up_write(&conn->session_lock);
802 up_write(&sessions_table_lock);
803 }
804
ksmbd_preauth_session_id_match(struct preauth_session * sess,unsigned long long id)805 static bool ksmbd_preauth_session_id_match(struct preauth_session *sess,
806 unsigned long long id)
807 {
808 return sess->id == id;
809 }
810
ksmbd_preauth_session_lookup(struct ksmbd_conn * conn,unsigned long long id)811 struct preauth_session *ksmbd_preauth_session_lookup(struct ksmbd_conn *conn,
812 unsigned long long id)
813 {
814 struct preauth_session *sess = NULL;
815
816 list_for_each_entry(sess, &conn->preauth_sess_table, preauth_entry) {
817 if (ksmbd_preauth_session_id_match(sess, id))
818 return sess;
819 }
820 return NULL;
821 }
822
__init_smb2_session(struct ksmbd_session * sess)823 static int __init_smb2_session(struct ksmbd_session *sess)
824 {
825 int id = ksmbd_acquire_smb2_uid(&session_ida);
826
827 if (id < 0)
828 return -EINVAL;
829 sess->id = id;
830 return 0;
831 }
832
__session_create(int protocol)833 static struct ksmbd_session *__session_create(int protocol)
834 {
835 struct ksmbd_session *sess;
836 int ret;
837
838 if (protocol != CIFDS_SESSION_FLAG_SMB2)
839 return NULL;
840
841 sess = kzalloc_obj(struct ksmbd_session, KSMBD_DEFAULT_GFP);
842 if (!sess)
843 return NULL;
844
845 ida_init(&sess->tree_conn_ida);
846
847 if (ksmbd_init_file_table(&sess->file_table))
848 goto error;
849
850 sess->last_active = jiffies;
851 sess->state = SMB2_SESSION_IN_PROGRESS;
852 set_session_flag(sess, protocol);
853 xa_init(&sess->tree_conns);
854 xa_init(&sess->ksmbd_chann_list);
855 xa_init(&sess->rpc_handle_list);
856 sess->sequence_number = 1;
857 atomic_set(&sess->refcnt, 2);
858 init_rwsem(&sess->tree_conns_lock);
859 init_rwsem(&sess->rpc_lock);
860 init_rwsem(&sess->chann_lock);
861
862 ret = __init_smb2_session(sess);
863 if (ret)
864 goto error;
865
866 down_write(&sessions_table_lock);
867 hash_add(sessions_table, &sess->hlist, sess->id);
868 ksmbd_counter_inc(KSMBD_COUNTER_SESSIONS);
869 up_write(&sessions_table_lock);
870
871 if (create_proc_session(sess))
872 pr_warn_ratelimited("Unable to create session %llu procfs entry\n", sess->id);
873 return sess;
874
875 error:
876 ksmbd_session_destroy(sess);
877 return NULL;
878 }
879
ksmbd_smb2_session_create(void)880 struct ksmbd_session *ksmbd_smb2_session_create(void)
881 {
882 return __session_create(CIFDS_SESSION_FLAG_SMB2);
883 }
884
ksmbd_acquire_tree_conn_id(struct ksmbd_session * sess)885 int ksmbd_acquire_tree_conn_id(struct ksmbd_session *sess)
886 {
887 int id = -EINVAL;
888
889 if (test_session_flag(sess, CIFDS_SESSION_FLAG_SMB2))
890 id = ksmbd_acquire_smb2_tid(&sess->tree_conn_ida);
891
892 return id;
893 }
894
ksmbd_release_tree_conn_id(struct ksmbd_session * sess,int id)895 void ksmbd_release_tree_conn_id(struct ksmbd_session *sess, int id)
896 {
897 if (id >= 0)
898 ksmbd_release_id(&sess->tree_conn_ida, id);
899 }
900