summaryrefslogtreecommitdiff
path: root/fs/smb/server/mgmt/user_session.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/smb/server/mgmt/user_session.c')
-rw-r--r--fs/smb/server/mgmt/user_session.c216
1 files changed, 216 insertions, 0 deletions
diff --git a/fs/smb/server/mgmt/user_session.c b/fs/smb/server/mgmt/user_session.c
index 7d880ff34402..68b3e0cb54d3 100644
--- a/fs/smb/server/mgmt/user_session.c
+++ b/fs/smb/server/mgmt/user_session.c
@@ -12,9 +12,12 @@
#include "user_session.h"
#include "user_config.h"
#include "tree_connect.h"
+#include "share_config.h"
#include "../transport_ipc.h"
#include "../connection.h"
#include "../vfs_cache.h"
+#include "../misc.h"
+#include "../stats.h"
static DEFINE_IDA(session_ida);
@@ -27,6 +30,215 @@ struct ksmbd_session_rpc {
unsigned int method;
};
+#ifdef CONFIG_PROC_FS
+
+static const struct ksmbd_const_name ksmbd_sess_cap_const_names[] = {
+ {SMB2_GLOBAL_CAP_DFS, "dfs"},
+ {SMB2_GLOBAL_CAP_LEASING, "lease"},
+ {SMB2_GLOBAL_CAP_LARGE_MTU, "large-mtu"},
+ {SMB2_GLOBAL_CAP_MULTI_CHANNEL, "multi-channel"},
+ {SMB2_GLOBAL_CAP_PERSISTENT_HANDLES, "persistent-handles"},
+ {SMB2_GLOBAL_CAP_DIRECTORY_LEASING, "dir-lease"},
+ {SMB2_GLOBAL_CAP_ENCRYPTION, "encryption"}
+};
+
+static const struct ksmbd_const_name ksmbd_cipher_const_names[] = {
+ {le16_to_cpu(SMB2_ENCRYPTION_AES128_CCM), "aes128-ccm"},
+ {le16_to_cpu(SMB2_ENCRYPTION_AES128_GCM), "aes128-gcm"},
+ {le16_to_cpu(SMB2_ENCRYPTION_AES256_CCM), "aes256-ccm"},
+ {le16_to_cpu(SMB2_ENCRYPTION_AES256_GCM), "aes256-gcm"},
+};
+
+static const struct ksmbd_const_name ksmbd_signing_const_names[] = {
+ {SIGNING_ALG_HMAC_SHA256, "hmac-sha256"},
+ {SIGNING_ALG_AES_CMAC, "aes-cmac"},
+ {SIGNING_ALG_AES_GMAC, "aes-gmac"},
+};
+
+static const char *session_state_string(struct ksmbd_session *session)
+{
+ switch (session->state) {
+ case SMB2_SESSION_VALID:
+ return "valid";
+ case SMB2_SESSION_IN_PROGRESS:
+ return "progress";
+ case SMB2_SESSION_EXPIRED:
+ return "expired";
+ default:
+ return "";
+ }
+}
+
+static const char *session_user_name(struct ksmbd_session *session)
+{
+ if (user_guest(session->user))
+ return "(Guest)";
+ else if (ksmbd_anonymous_user(session->user))
+ return "(Anonymous)";
+ return session->user->name;
+}
+
+static int show_proc_session(struct seq_file *m, void *v)
+{
+ struct ksmbd_session *sess;
+ struct ksmbd_tree_connect *tree_conn;
+ struct ksmbd_share_config *share_conf;
+ struct channel *chan;
+ unsigned long id;
+ int i = 0;
+
+ sess = (struct ksmbd_session *)m->private;
+ ksmbd_user_session_get(sess);
+
+ i = 0;
+ xa_for_each(&sess->ksmbd_chann_list, id, chan) {
+#if IS_ENABLED(CONFIG_IPV6)
+ if (chan->conn->inet_addr)
+ seq_printf(m, "%-20s\t%pI4\n", "client",
+ &chan->conn->inet_addr);
+ else
+ seq_printf(m, "%-20s\t%pI6c\n", "client",
+ &chan->conn->inet6_addr);
+#else
+ seq_printf(m, "%-20s\t%pI4\n", "client",
+ &chan->conn->inet_addr);
+#endif
+ seq_printf(m, "%-20s\t%s\n", "user", session_user_name(sess));
+ seq_printf(m, "%-20s\t%llu\n", "id", sess->id);
+ seq_printf(m, "%-20s\t%s\n", "state",
+ session_state_string(sess));
+
+ seq_printf(m, "%-20s\t", "capabilities");
+ ksmbd_proc_show_flag_names(m,
+ ksmbd_sess_cap_const_names,
+ ARRAY_SIZE(ksmbd_sess_cap_const_names),
+ chan->conn->vals->req_capabilities);
+
+ if (sess->sign) {
+ seq_printf(m, "%-20s\t", "signing");
+ ksmbd_proc_show_const_name(m, "%s\t",
+ ksmbd_signing_const_names,
+ ARRAY_SIZE(ksmbd_signing_const_names),
+ le16_to_cpu(chan->conn->signing_algorithm));
+ } else if (sess->enc) {
+ seq_printf(m, "%-20s\t", "encryption");
+ ksmbd_proc_show_const_name(m, "%s\t",
+ ksmbd_cipher_const_names,
+ ARRAY_SIZE(ksmbd_cipher_const_names),
+ le16_to_cpu(chan->conn->cipher_type));
+ }
+ i++;
+ }
+
+ seq_printf(m, "%-20s\t%d\n", "channels", i);
+
+ i = 0;
+ xa_for_each(&sess->tree_conns, id, tree_conn) {
+ share_conf = tree_conn->share_conf;
+ seq_printf(m, "%-20s\t%s\t%8d", "share",
+ share_conf->name, tree_conn->id);
+ if (test_share_config_flag(share_conf, KSMBD_SHARE_FLAG_PIPE))
+ seq_printf(m, " %s ", "pipe");
+ else
+ seq_printf(m, " %s ", "disk");
+ seq_putc(m, '\n');
+ }
+
+ ksmbd_user_session_put(sess);
+ return 0;
+}
+
+void ksmbd_proc_show_flag_names(struct seq_file *m,
+ const struct ksmbd_const_name *table,
+ int count,
+ unsigned int flags)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if (table[i].const_value & flags)
+ seq_printf(m, "0x%08x\t", table[i].const_value);
+ }
+ seq_putc(m, '\n');
+}
+
+void ksmbd_proc_show_const_name(struct seq_file *m,
+ const char *format,
+ const struct ksmbd_const_name *table,
+ int count,
+ unsigned int const_value)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if (table[i].const_value & const_value)
+ seq_printf(m, format, table[i].name);
+ }
+ seq_putc(m, '\n');
+}
+
+static int create_proc_session(struct ksmbd_session *sess)
+{
+ char name[30];
+
+ snprintf(name, sizeof(name), "sessions/%llu", sess->id);
+ sess->proc_entry = ksmbd_proc_create(name,
+ show_proc_session, sess);
+ return 0;
+}
+
+static void delete_proc_session(struct ksmbd_session *sess)
+{
+ if (sess->proc_entry)
+ proc_remove(sess->proc_entry);
+}
+
+static int show_proc_sessions(struct seq_file *m, void *v)
+{
+ struct ksmbd_session *session;
+ struct channel *chan;
+ int i;
+ unsigned long id;
+
+ seq_printf(m, "#%-40s %-15s %-10s %-10s\n",
+ "<client>", "<user>", "<sess_id>", "<state>");
+
+ down_read(&sessions_table_lock);
+ hash_for_each(sessions_table, i, session, hlist) {
+ xa_for_each(&session->ksmbd_chann_list, id, chan) {
+ down_read(&chan->conn->session_lock);
+ ksmbd_user_session_get(session);
+
+ if (chan->conn->inet_addr)
+ seq_printf(m, " %-40pI4", &chan->conn->inet_addr);
+ else
+ seq_printf(m, " %-40pI6c", &chan->conn->inet6_addr);
+ seq_printf(m, " %-15s %-10llu %-10s\n",
+ session_user_name(session),
+ session->id,
+ session_state_string(session));
+
+ ksmbd_user_session_put(session);
+ up_read(&chan->conn->session_lock);
+ }
+ }
+ up_read(&sessions_table_lock);
+ return 0;
+}
+
+int create_proc_sessions(void)
+{
+ if (!ksmbd_proc_create("sessions/sessions",
+ show_proc_sessions, NULL))
+ return -ENOMEM;
+ return 0;
+}
+#else
+int create_proc_sessions(void) { return 0; }
+static int create_proc_session(struct ksmbd_session *sess) { return 0; }
+static void delete_proc_session(struct ksmbd_session *sess) {}
+#endif
+
static void free_channel_list(struct ksmbd_session *sess)
{
struct channel *chann;
@@ -159,6 +371,8 @@ void ksmbd_session_destroy(struct ksmbd_session *sess)
if (!sess)
return;
+ delete_proc_session(sess);
+
if (sess->user)
ksmbd_free_user(sess->user);
@@ -465,6 +679,8 @@ static struct ksmbd_session *__session_create(int protocol)
hash_add(sessions_table, &sess->hlist, sess->id);
up_write(&sessions_table_lock);
+ create_proc_session(sess);
+ ksmbd_counter_inc(KSMBD_COUNTER_SESSIONS);
return sess;
error: