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