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