1919#include "misc.h"
2020#include "mgmt/tree_connect.h"
2121#include "mgmt/user_session.h"
22+ #include "mgmt/user_config.h"
2223#include "smb_common.h"
2324#include "server.h"
2425#include "smb2pdu.h"
@@ -476,6 +477,8 @@ static void __ksmbd_close_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp)
476477
477478 if (ksmbd_stream_fd (fp ))
478479 kfree (fp -> stream .name );
480+ kfree (fp -> owner .name );
481+
479482 kmem_cache_free (filp_cache , fp );
480483}
481484
@@ -787,11 +790,13 @@ void ksmbd_update_fstate(struct ksmbd_file_table *ft, struct ksmbd_file *fp,
787790}
788791
789792static int
790- __close_file_table_ids (struct ksmbd_file_table * ft ,
793+ __close_file_table_ids (struct ksmbd_session * sess ,
791794 struct ksmbd_tree_connect * tcon ,
792795 bool (* skip )(struct ksmbd_tree_connect * tcon ,
793- struct ksmbd_file * fp ))
796+ struct ksmbd_file * fp ,
797+ struct ksmbd_user * user ))
794798{
799+ struct ksmbd_file_table * ft = & sess -> file_table ;
795800 struct ksmbd_file * fp ;
796801 unsigned int id = 0 ;
797802 int num = 0 ;
@@ -804,7 +809,7 @@ __close_file_table_ids(struct ksmbd_file_table *ft,
804809 break ;
805810 }
806811
807- if (skip (tcon , fp ) ||
812+ if (skip (tcon , fp , sess -> user ) ||
808813 !atomic_dec_and_test (& fp -> refcount )) {
809814 id ++ ;
810815 write_unlock (& ft -> lock );
@@ -856,7 +861,8 @@ static inline bool is_reconnectable(struct ksmbd_file *fp)
856861}
857862
858863static bool tree_conn_fd_check (struct ksmbd_tree_connect * tcon ,
859- struct ksmbd_file * fp )
864+ struct ksmbd_file * fp ,
865+ struct ksmbd_user * user )
860866{
861867 return fp -> tcon != tcon ;
862868}
@@ -991,8 +997,62 @@ void ksmbd_stop_durable_scavenger(void)
991997 kthread_stop (server_conf .dh_task );
992998}
993999
1000+ /*
1001+ * ksmbd_vfs_copy_durable_owner - Copy owner info for durable reconnect
1002+ * @fp: ksmbd file pointer to store owner info
1003+ * @user: user pointer to copy from
1004+ *
1005+ * This function binds the current user's identity to the file handle
1006+ * to satisfy MS-SMB2 Step 8 (SecurityContext matching) during reconnect.
1007+ *
1008+ * Return: 0 on success, or negative error code on failure
1009+ */
1010+ static int ksmbd_vfs_copy_durable_owner (struct ksmbd_file * fp ,
1011+ struct ksmbd_user * user )
1012+ {
1013+ if (!user )
1014+ return - EINVAL ;
1015+
1016+ /* Duplicate the user name to ensure identity persistence */
1017+ fp -> owner .name = kstrdup (user -> name , GFP_KERNEL );
1018+ if (!fp -> owner .name )
1019+ return - ENOMEM ;
1020+
1021+ fp -> owner .uid = user -> uid ;
1022+ fp -> owner .gid = user -> gid ;
1023+
1024+ return 0 ;
1025+ }
1026+
1027+ /**
1028+ * ksmbd_vfs_compare_durable_owner - Verify if the requester is original owner
1029+ * @fp: existing ksmbd file pointer
1030+ * @user: user pointer of the reconnect requester
1031+ *
1032+ * Compares the UID, GID, and name of the current requester against the
1033+ * original owner stored in the file handle.
1034+ *
1035+ * Return: true if the user matches, false otherwise
1036+ */
1037+ bool ksmbd_vfs_compare_durable_owner (struct ksmbd_file * fp ,
1038+ struct ksmbd_user * user )
1039+ {
1040+ if (!user || !fp -> owner .name )
1041+ return false;
1042+
1043+ /* Check if the UID and GID match first (fast path) */
1044+ if (fp -> owner .uid != user -> uid || fp -> owner .gid != user -> gid )
1045+ return false;
1046+
1047+ /* Validate the account name to ensure the same SecurityContext */
1048+ if (strcmp (fp -> owner .name , user -> name ))
1049+ return false;
1050+
1051+ return true;
1052+ }
1053+
9941054static bool session_fd_check (struct ksmbd_tree_connect * tcon ,
995- struct ksmbd_file * fp )
1055+ struct ksmbd_file * fp , struct ksmbd_user * user )
9961056{
9971057 struct ksmbd_inode * ci ;
9981058 struct oplock_info * op ;
@@ -1002,6 +1062,9 @@ static bool session_fd_check(struct ksmbd_tree_connect *tcon,
10021062 if (!is_reconnectable (fp ))
10031063 return false;
10041064
1065+ if (ksmbd_vfs_copy_durable_owner (fp , user ))
1066+ return false;
1067+
10051068 conn = fp -> conn ;
10061069 ci = fp -> f_ci ;
10071070 down_write (& ci -> m_lock );
@@ -1033,7 +1096,7 @@ static bool session_fd_check(struct ksmbd_tree_connect *tcon,
10331096
10341097void ksmbd_close_tree_conn_fds (struct ksmbd_work * work )
10351098{
1036- int num = __close_file_table_ids (& work -> sess -> file_table ,
1099+ int num = __close_file_table_ids (work -> sess ,
10371100 work -> tcon ,
10381101 tree_conn_fd_check );
10391102
@@ -1042,7 +1105,7 @@ void ksmbd_close_tree_conn_fds(struct ksmbd_work *work)
10421105
10431106void ksmbd_close_session_fds (struct ksmbd_work * work )
10441107{
1045- int num = __close_file_table_ids (& work -> sess -> file_table ,
1108+ int num = __close_file_table_ids (work -> sess ,
10461109 work -> tcon ,
10471110 session_fd_check );
10481111
@@ -1140,6 +1203,10 @@ int ksmbd_reopen_durable_fd(struct ksmbd_work *work, struct ksmbd_file *fp)
11401203 }
11411204 up_write (& ci -> m_lock );
11421205
1206+ fp -> owner .uid = fp -> owner .gid = 0 ;
1207+ kfree (fp -> owner .name );
1208+ fp -> owner .name = NULL ;
1209+
11431210 return 0 ;
11441211}
11451212
@@ -1154,12 +1221,14 @@ int ksmbd_init_file_table(struct ksmbd_file_table *ft)
11541221 return 0 ;
11551222}
11561223
1157- void ksmbd_destroy_file_table (struct ksmbd_file_table * ft )
1224+ void ksmbd_destroy_file_table (struct ksmbd_session * sess )
11581225{
1226+ struct ksmbd_file_table * ft = & sess -> file_table ;
1227+
11591228 if (!ft -> idr )
11601229 return ;
11611230
1162- __close_file_table_ids (ft , NULL , session_fd_check );
1231+ __close_file_table_ids (sess , NULL , session_fd_check );
11631232 idr_destroy (ft -> idr );
11641233 kfree (ft -> idr );
11651234 ft -> idr = NULL ;
0 commit comments