]> Git Repo - J-linux.git/blob - fs/smb/server/server.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / fs / smb / server / server.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *   Copyright (C) 2016 Namjae Jeon <[email protected]>
4  *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
5  */
6
7 #include "glob.h"
8 #include "oplock.h"
9 #include "misc.h"
10 #include <linux/sched/signal.h>
11 #include <linux/workqueue.h>
12 #include <linux/sysfs.h>
13 #include <linux/module.h>
14 #include <linux/moduleparam.h>
15
16 #include "server.h"
17 #include "smb_common.h"
18 #include "../common/smb2status.h"
19 #include "connection.h"
20 #include "transport_ipc.h"
21 #include "mgmt/user_session.h"
22 #include "crypto_ctx.h"
23 #include "auth.h"
24
25 int ksmbd_debug_types;
26
27 struct ksmbd_server_config server_conf;
28
29 enum SERVER_CTRL_TYPE {
30         SERVER_CTRL_TYPE_INIT,
31         SERVER_CTRL_TYPE_RESET,
32 };
33
34 struct server_ctrl_struct {
35         int                     type;
36         struct work_struct      ctrl_work;
37 };
38
39 static DEFINE_MUTEX(ctrl_lock);
40
41 static int ___server_conf_set(int idx, char *val)
42 {
43         if (idx >= ARRAY_SIZE(server_conf.conf))
44                 return -EINVAL;
45
46         if (!val || val[0] == 0x00)
47                 return -EINVAL;
48
49         kfree(server_conf.conf[idx]);
50         server_conf.conf[idx] = kstrdup(val, KSMBD_DEFAULT_GFP);
51         if (!server_conf.conf[idx])
52                 return -ENOMEM;
53         return 0;
54 }
55
56 int ksmbd_set_netbios_name(char *v)
57 {
58         return ___server_conf_set(SERVER_CONF_NETBIOS_NAME, v);
59 }
60
61 int ksmbd_set_server_string(char *v)
62 {
63         return ___server_conf_set(SERVER_CONF_SERVER_STRING, v);
64 }
65
66 int ksmbd_set_work_group(char *v)
67 {
68         return ___server_conf_set(SERVER_CONF_WORK_GROUP, v);
69 }
70
71 char *ksmbd_netbios_name(void)
72 {
73         return server_conf.conf[SERVER_CONF_NETBIOS_NAME];
74 }
75
76 char *ksmbd_server_string(void)
77 {
78         return server_conf.conf[SERVER_CONF_SERVER_STRING];
79 }
80
81 char *ksmbd_work_group(void)
82 {
83         return server_conf.conf[SERVER_CONF_WORK_GROUP];
84 }
85
86 /**
87  * check_conn_state() - check state of server thread connection
88  * @work:     smb work containing server thread information
89  *
90  * Return:      0 on valid connection, otherwise 1 to reconnect
91  */
92 static inline int check_conn_state(struct ksmbd_work *work)
93 {
94         struct smb_hdr *rsp_hdr;
95
96         if (ksmbd_conn_exiting(work->conn) ||
97             ksmbd_conn_need_reconnect(work->conn)) {
98                 rsp_hdr = work->response_buf;
99                 rsp_hdr->Status.CifsError = STATUS_CONNECTION_DISCONNECTED;
100                 return 1;
101         }
102         return 0;
103 }
104
105 #define SERVER_HANDLER_CONTINUE         0
106 #define SERVER_HANDLER_ABORT            1
107
108 static int __process_request(struct ksmbd_work *work, struct ksmbd_conn *conn,
109                              u16 *cmd)
110 {
111         struct smb_version_cmds *cmds;
112         u16 command;
113         int ret;
114
115         if (check_conn_state(work))
116                 return SERVER_HANDLER_CONTINUE;
117
118         if (ksmbd_verify_smb_message(work)) {
119                 conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER);
120                 return SERVER_HANDLER_ABORT;
121         }
122
123         command = conn->ops->get_cmd_val(work);
124         *cmd = command;
125
126 andx_again:
127         if (command >= conn->max_cmds) {
128                 conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER);
129                 return SERVER_HANDLER_CONTINUE;
130         }
131
132         cmds = &conn->cmds[command];
133         if (!cmds->proc) {
134                 ksmbd_debug(SMB, "*** not implemented yet cmd = %x\n", command);
135                 conn->ops->set_rsp_status(work, STATUS_NOT_IMPLEMENTED);
136                 return SERVER_HANDLER_CONTINUE;
137         }
138
139         if (work->sess && conn->ops->is_sign_req(work, command)) {
140                 ret = conn->ops->check_sign_req(work);
141                 if (!ret) {
142                         conn->ops->set_rsp_status(work, STATUS_ACCESS_DENIED);
143                         return SERVER_HANDLER_CONTINUE;
144                 }
145         }
146
147         ret = cmds->proc(work);
148
149         if (ret < 0)
150                 ksmbd_debug(CONN, "Failed to process %u [%d]\n", command, ret);
151         /* AndX commands - chained request can return positive values */
152         else if (ret > 0) {
153                 command = ret;
154                 *cmd = command;
155                 goto andx_again;
156         }
157
158         if (work->send_no_response)
159                 return SERVER_HANDLER_ABORT;
160         return SERVER_HANDLER_CONTINUE;
161 }
162
163 static void __handle_ksmbd_work(struct ksmbd_work *work,
164                                 struct ksmbd_conn *conn)
165 {
166         u16 command = 0;
167         int rc;
168         bool is_chained = false;
169
170         if (conn->ops->is_transform_hdr &&
171             conn->ops->is_transform_hdr(work->request_buf)) {
172                 rc = conn->ops->decrypt_req(work);
173                 if (rc < 0)
174                         return;
175                 work->encrypted = true;
176         }
177
178         if (conn->ops->allocate_rsp_buf(work))
179                 return;
180
181         rc = conn->ops->init_rsp_hdr(work);
182         if (rc) {
183                 /* either uid or tid is not correct */
184                 conn->ops->set_rsp_status(work, STATUS_INVALID_HANDLE);
185                 goto send;
186         }
187
188         do {
189                 if (conn->ops->check_user_session) {
190                         rc = conn->ops->check_user_session(work);
191                         if (rc < 0) {
192                                 if (rc == -EINVAL)
193                                         conn->ops->set_rsp_status(work,
194                                                 STATUS_INVALID_PARAMETER);
195                                 else
196                                         conn->ops->set_rsp_status(work,
197                                                 STATUS_USER_SESSION_DELETED);
198                                 goto send;
199                         } else if (rc > 0) {
200                                 rc = conn->ops->get_ksmbd_tcon(work);
201                                 if (rc < 0) {
202                                         if (rc == -EINVAL)
203                                                 conn->ops->set_rsp_status(work,
204                                                         STATUS_INVALID_PARAMETER);
205                                         else
206                                                 conn->ops->set_rsp_status(work,
207                                                         STATUS_NETWORK_NAME_DELETED);
208                                         goto send;
209                                 }
210                         }
211                 }
212
213                 rc = __process_request(work, conn, &command);
214                 if (rc == SERVER_HANDLER_ABORT)
215                         break;
216
217                 /*
218                  * Call smb2_set_rsp_credits() function to set number of credits
219                  * granted in hdr of smb2 response.
220                  */
221                 if (conn->ops->set_rsp_credits) {
222                         spin_lock(&conn->credits_lock);
223                         rc = conn->ops->set_rsp_credits(work);
224                         spin_unlock(&conn->credits_lock);
225                         if (rc < 0) {
226                                 conn->ops->set_rsp_status(work,
227                                         STATUS_INVALID_PARAMETER);
228                                 goto send;
229                         }
230                 }
231
232                 is_chained = is_chained_smb2_message(work);
233
234                 if (work->sess &&
235                     (work->sess->sign || smb3_11_final_sess_setup_resp(work) ||
236                      conn->ops->is_sign_req(work, command)))
237                         conn->ops->set_sign_rsp(work);
238         } while (is_chained == true);
239
240 send:
241         if (work->tcon)
242                 ksmbd_tree_connect_put(work->tcon);
243         smb3_preauth_hash_rsp(work);
244         if (work->sess && work->sess->enc && work->encrypted &&
245             conn->ops->encrypt_resp) {
246                 rc = conn->ops->encrypt_resp(work);
247                 if (rc < 0)
248                         conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
249         }
250         if (work->sess)
251                 ksmbd_user_session_put(work->sess);
252
253         ksmbd_conn_write(work);
254 }
255
256 /**
257  * handle_ksmbd_work() - process pending smb work requests
258  * @wk: smb work containing request command buffer
259  *
260  * called by kworker threads to processing remaining smb work requests
261  */
262 static void handle_ksmbd_work(struct work_struct *wk)
263 {
264         struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work);
265         struct ksmbd_conn *conn = work->conn;
266
267         atomic64_inc(&conn->stats.request_served);
268
269         __handle_ksmbd_work(work, conn);
270
271         ksmbd_conn_try_dequeue_request(work);
272         ksmbd_free_work_struct(work);
273         /*
274          * Checking waitqueue to dropping pending requests on
275          * disconnection. waitqueue_active is safe because it
276          * uses atomic operation for condition.
277          */
278         atomic_inc(&conn->refcnt);
279         if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
280                 wake_up(&conn->r_count_q);
281
282         if (atomic_dec_and_test(&conn->refcnt))
283                 kfree(conn);
284 }
285
286 /**
287  * queue_ksmbd_work() - queue a smb request to worker thread queue
288  *              for processing smb command and sending response
289  * @conn:       connection instance
290  *
291  * read remaining data from socket create and submit work.
292  */
293 static int queue_ksmbd_work(struct ksmbd_conn *conn)
294 {
295         struct ksmbd_work *work;
296         int err;
297
298         err = ksmbd_init_smb_server(conn);
299         if (err)
300                 return 0;
301
302         work = ksmbd_alloc_work_struct();
303         if (!work) {
304                 pr_err("allocation for work failed\n");
305                 return -ENOMEM;
306         }
307
308         work->conn = conn;
309         work->request_buf = conn->request_buf;
310         conn->request_buf = NULL;
311
312         ksmbd_conn_enqueue_request(work);
313         atomic_inc(&conn->r_count);
314         /* update activity on connection */
315         conn->last_active = jiffies;
316         INIT_WORK(&work->work, handle_ksmbd_work);
317         ksmbd_queue_work(work);
318         return 0;
319 }
320
321 static int ksmbd_server_process_request(struct ksmbd_conn *conn)
322 {
323         return queue_ksmbd_work(conn);
324 }
325
326 static int ksmbd_server_terminate_conn(struct ksmbd_conn *conn)
327 {
328         ksmbd_sessions_deregister(conn);
329         destroy_lease_table(conn);
330         return 0;
331 }
332
333 static void ksmbd_server_tcp_callbacks_init(void)
334 {
335         struct ksmbd_conn_ops ops;
336
337         ops.process_fn = ksmbd_server_process_request;
338         ops.terminate_fn = ksmbd_server_terminate_conn;
339
340         ksmbd_conn_init_server_callbacks(&ops);
341 }
342
343 static void server_conf_free(void)
344 {
345         int i;
346
347         for (i = 0; i < ARRAY_SIZE(server_conf.conf); i++) {
348                 kfree(server_conf.conf[i]);
349                 server_conf.conf[i] = NULL;
350         }
351 }
352
353 static int server_conf_init(void)
354 {
355         WRITE_ONCE(server_conf.state, SERVER_STATE_STARTING_UP);
356         server_conf.enforced_signing = 0;
357         server_conf.min_protocol = ksmbd_min_protocol();
358         server_conf.max_protocol = ksmbd_max_protocol();
359         server_conf.auth_mechs = KSMBD_AUTH_NTLMSSP;
360 #ifdef CONFIG_SMB_SERVER_KERBEROS5
361         server_conf.auth_mechs |= KSMBD_AUTH_KRB5 |
362                                 KSMBD_AUTH_MSKRB5;
363 #endif
364         server_conf.max_inflight_req = SMB2_MAX_CREDITS;
365         return 0;
366 }
367
368 static void server_ctrl_handle_init(struct server_ctrl_struct *ctrl)
369 {
370         int ret;
371
372         ret = ksmbd_conn_transport_init();
373         if (ret) {
374                 server_queue_ctrl_reset_work();
375                 return;
376         }
377
378         WRITE_ONCE(server_conf.state, SERVER_STATE_RUNNING);
379 }
380
381 static void server_ctrl_handle_reset(struct server_ctrl_struct *ctrl)
382 {
383         ksmbd_ipc_soft_reset();
384         ksmbd_conn_transport_destroy();
385         ksmbd_stop_durable_scavenger();
386         server_conf_free();
387         server_conf_init();
388         WRITE_ONCE(server_conf.state, SERVER_STATE_STARTING_UP);
389 }
390
391 static void server_ctrl_handle_work(struct work_struct *work)
392 {
393         struct server_ctrl_struct *ctrl;
394
395         ctrl = container_of(work, struct server_ctrl_struct, ctrl_work);
396
397         mutex_lock(&ctrl_lock);
398         switch (ctrl->type) {
399         case SERVER_CTRL_TYPE_INIT:
400                 server_ctrl_handle_init(ctrl);
401                 break;
402         case SERVER_CTRL_TYPE_RESET:
403                 server_ctrl_handle_reset(ctrl);
404                 break;
405         default:
406                 pr_err("Unknown server work type: %d\n", ctrl->type);
407         }
408         mutex_unlock(&ctrl_lock);
409         kfree(ctrl);
410         module_put(THIS_MODULE);
411 }
412
413 static int __queue_ctrl_work(int type)
414 {
415         struct server_ctrl_struct *ctrl;
416
417         ctrl = kmalloc(sizeof(struct server_ctrl_struct), KSMBD_DEFAULT_GFP);
418         if (!ctrl)
419                 return -ENOMEM;
420
421         __module_get(THIS_MODULE);
422         ctrl->type = type;
423         INIT_WORK(&ctrl->ctrl_work, server_ctrl_handle_work);
424         queue_work(system_long_wq, &ctrl->ctrl_work);
425         return 0;
426 }
427
428 int server_queue_ctrl_init_work(void)
429 {
430         return __queue_ctrl_work(SERVER_CTRL_TYPE_INIT);
431 }
432
433 int server_queue_ctrl_reset_work(void)
434 {
435         return __queue_ctrl_work(SERVER_CTRL_TYPE_RESET);
436 }
437
438 static ssize_t stats_show(const struct class *class, const struct class_attribute *attr,
439                           char *buf)
440 {
441         /*
442          * Inc this each time you change stats output format,
443          * so user space will know what to do.
444          */
445         static int stats_version = 2;
446         static const char * const state[] = {
447                 "startup",
448                 "running",
449                 "reset",
450                 "shutdown"
451         };
452         return sysfs_emit(buf, "%d %s %d %lu\n", stats_version,
453                           state[server_conf.state], server_conf.tcp_port,
454                           server_conf.ipc_last_active / HZ);
455 }
456
457 static ssize_t kill_server_store(const struct class *class,
458                                  const struct class_attribute *attr, const char *buf,
459                                  size_t len)
460 {
461         if (!sysfs_streq(buf, "hard"))
462                 return len;
463
464         pr_info("kill command received\n");
465         mutex_lock(&ctrl_lock);
466         WRITE_ONCE(server_conf.state, SERVER_STATE_RESETTING);
467         __module_get(THIS_MODULE);
468         server_ctrl_handle_reset(NULL);
469         module_put(THIS_MODULE);
470         mutex_unlock(&ctrl_lock);
471         return len;
472 }
473
474 static const char * const debug_type_strings[] = {"smb", "auth", "vfs",
475                                                   "oplock", "ipc", "conn",
476                                                   "rdma"};
477
478 static ssize_t debug_show(const struct class *class, const struct class_attribute *attr,
479                           char *buf)
480 {
481         ssize_t sz = 0;
482         int i, pos = 0;
483
484         for (i = 0; i < ARRAY_SIZE(debug_type_strings); i++) {
485                 if ((ksmbd_debug_types >> i) & 1) {
486                         pos = sysfs_emit_at(buf, sz, "[%s] ", debug_type_strings[i]);
487                 } else {
488                         pos = sysfs_emit_at(buf, sz, "%s ", debug_type_strings[i]);
489                 }
490                 sz += pos;
491         }
492         sz += sysfs_emit_at(buf, sz, "\n");
493         return sz;
494 }
495
496 static ssize_t debug_store(const struct class *class, const struct class_attribute *attr,
497                            const char *buf, size_t len)
498 {
499         int i;
500
501         for (i = 0; i < ARRAY_SIZE(debug_type_strings); i++) {
502                 if (sysfs_streq(buf, "all")) {
503                         if (ksmbd_debug_types == KSMBD_DEBUG_ALL)
504                                 ksmbd_debug_types = 0;
505                         else
506                                 ksmbd_debug_types = KSMBD_DEBUG_ALL;
507                         break;
508                 }
509
510                 if (sysfs_streq(buf, debug_type_strings[i])) {
511                         if (ksmbd_debug_types & (1 << i))
512                                 ksmbd_debug_types &= ~(1 << i);
513                         else
514                                 ksmbd_debug_types |= (1 << i);
515                         break;
516                 }
517         }
518
519         return len;
520 }
521
522 static CLASS_ATTR_RO(stats);
523 static CLASS_ATTR_WO(kill_server);
524 static CLASS_ATTR_RW(debug);
525
526 static struct attribute *ksmbd_control_class_attrs[] = {
527         &class_attr_stats.attr,
528         &class_attr_kill_server.attr,
529         &class_attr_debug.attr,
530         NULL,
531 };
532 ATTRIBUTE_GROUPS(ksmbd_control_class);
533
534 static struct class ksmbd_control_class = {
535         .name           = "ksmbd-control",
536         .class_groups   = ksmbd_control_class_groups,
537 };
538
539 static int ksmbd_server_shutdown(void)
540 {
541         WRITE_ONCE(server_conf.state, SERVER_STATE_SHUTTING_DOWN);
542
543         class_unregister(&ksmbd_control_class);
544         ksmbd_workqueue_destroy();
545         ksmbd_ipc_release();
546         ksmbd_conn_transport_destroy();
547         ksmbd_crypto_destroy();
548         ksmbd_free_global_file_table();
549         destroy_lease_table(NULL);
550         ksmbd_work_pool_destroy();
551         ksmbd_exit_file_cache();
552         server_conf_free();
553         return 0;
554 }
555
556 static int __init ksmbd_server_init(void)
557 {
558         int ret;
559
560         ret = class_register(&ksmbd_control_class);
561         if (ret) {
562                 pr_err("Unable to register ksmbd-control class\n");
563                 return ret;
564         }
565
566         ksmbd_server_tcp_callbacks_init();
567
568         ret = server_conf_init();
569         if (ret)
570                 goto err_unregister;
571
572         ret = ksmbd_work_pool_init();
573         if (ret)
574                 goto err_unregister;
575
576         ret = ksmbd_init_file_cache();
577         if (ret)
578                 goto err_destroy_work_pools;
579
580         ret = ksmbd_ipc_init();
581         if (ret)
582                 goto err_exit_file_cache;
583
584         ret = ksmbd_init_global_file_table();
585         if (ret)
586                 goto err_ipc_release;
587
588         ret = ksmbd_inode_hash_init();
589         if (ret)
590                 goto err_destroy_file_table;
591
592         ret = ksmbd_crypto_create();
593         if (ret)
594                 goto err_release_inode_hash;
595
596         ret = ksmbd_workqueue_init();
597         if (ret)
598                 goto err_crypto_destroy;
599
600         return 0;
601
602 err_crypto_destroy:
603         ksmbd_crypto_destroy();
604 err_release_inode_hash:
605         ksmbd_release_inode_hash();
606 err_destroy_file_table:
607         ksmbd_free_global_file_table();
608 err_ipc_release:
609         ksmbd_ipc_release();
610 err_exit_file_cache:
611         ksmbd_exit_file_cache();
612 err_destroy_work_pools:
613         ksmbd_work_pool_destroy();
614 err_unregister:
615         class_unregister(&ksmbd_control_class);
616
617         return ret;
618 }
619
620 /**
621  * ksmbd_server_exit() - shutdown forker thread and free memory at module exit
622  */
623 static void __exit ksmbd_server_exit(void)
624 {
625         ksmbd_server_shutdown();
626         rcu_barrier();
627         ksmbd_release_inode_hash();
628 }
629
630 MODULE_AUTHOR("Namjae Jeon <[email protected]>");
631 MODULE_DESCRIPTION("Linux kernel CIFS/SMB SERVER");
632 MODULE_LICENSE("GPL");
633 MODULE_SOFTDEP("pre: ecb");
634 MODULE_SOFTDEP("pre: hmac");
635 MODULE_SOFTDEP("pre: md5");
636 MODULE_SOFTDEP("pre: nls");
637 MODULE_SOFTDEP("pre: aes");
638 MODULE_SOFTDEP("pre: cmac");
639 MODULE_SOFTDEP("pre: sha256");
640 MODULE_SOFTDEP("pre: sha512");
641 MODULE_SOFTDEP("pre: aead2");
642 MODULE_SOFTDEP("pre: ccm");
643 MODULE_SOFTDEP("pre: gcm");
644 MODULE_SOFTDEP("pre: crc32");
645 module_init(ksmbd_server_init)
646 module_exit(ksmbd_server_exit)
This page took 0.097284 seconds and 4 git commands to generate.