Skip to content

Commit 227c3d5

Browse files
committed
Merge tag 'v7.1-rc2-ksmbd-server-fixes' of git://git.samba.org/ksmbd
Pull smb server fixes from Steve French: - Fix shutdown (stop sessions) - Fix readdir unsupported info level * tag 'v7.1-rc2-ksmbd-server-fixes' of git://git.samba.org/ksmbd: ksmbd: rewrite stop_sessions() with restartable iteration smb: server: handle readdir_info_level_struct_sz() error
2 parents 6fe0be6 + c444139 commit 227c3d5

3 files changed

Lines changed: 46 additions & 9 deletions

File tree

fs/smb/server/connection.c

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -540,24 +540,54 @@ int ksmbd_conn_transport_init(void)
540540

541541
static void stop_sessions(void)
542542
{
543-
struct ksmbd_conn *conn;
543+
struct ksmbd_conn *conn, *target;
544544
struct ksmbd_transport *t;
545+
bool any;
545546
int bkt;
546547

548+
/*
549+
* Serialised via init_lock; no concurrent stop_sessions() can
550+
* touch conn->stop_called, so writing it under the read lock is
551+
* safe.
552+
*/
547553
again:
554+
target = NULL;
555+
any = false;
548556
down_read(&conn_list_lock);
549557
hash_for_each(conn_list, bkt, conn, hlist) {
550-
t = conn->transport;
551-
ksmbd_conn_set_exiting(conn);
552-
if (t->ops->shutdown) {
553-
up_read(&conn_list_lock);
558+
any = true;
559+
if (conn->stop_called)
560+
continue;
561+
atomic_inc(&conn->refcnt);
562+
conn->stop_called = true;
563+
/*
564+
* Mark the connection EXITING while still holding the
565+
* read lock so the selection and the status transition
566+
* happen together. Do not regress a connection that has
567+
* already advanced to RELEASING on its own (e.g. the
568+
* handler exited its receive loop for an unrelated
569+
* reason).
570+
*/
571+
if (READ_ONCE(conn->status) != KSMBD_SESS_RELEASING)
572+
ksmbd_conn_set_exiting(conn);
573+
target = conn;
574+
break;
575+
}
576+
up_read(&conn_list_lock);
577+
578+
if (target) {
579+
t = target->transport;
580+
if (t->ops->shutdown)
554581
t->ops->shutdown(t);
555-
down_read(&conn_list_lock);
582+
if (atomic_dec_and_test(&target->refcnt)) {
583+
ida_destroy(&target->async_ida);
584+
t->ops->free_transport(t);
585+
kfree(target);
556586
}
587+
goto again;
557588
}
558-
up_read(&conn_list_lock);
559589

560-
if (!hash_empty(conn_list)) {
590+
if (any) {
561591
msleep(100);
562592
goto again;
563593
}

fs/smb/server/connection.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ struct ksmbd_conn {
4949
struct mutex srv_mutex;
5050
int status;
5151
unsigned int cli_cap;
52+
bool stop_called;
5253
union {
5354
__be32 inet_addr;
5455
#if IS_ENABLED(CONFIG_IPV6)

fs/smb/server/smb2pdu.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3946,7 +3946,13 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
39463946
goto free_conv_name;
39473947
}
39483948

3949-
struct_sz = readdir_info_level_struct_sz(info_level) + conv_len;
3949+
struct_sz = readdir_info_level_struct_sz(info_level);
3950+
if (struct_sz == -EOPNOTSUPP) {
3951+
rc = -EINVAL;
3952+
goto free_conv_name;
3953+
}
3954+
3955+
struct_sz += conv_len;
39503956
next_entry_offset = ALIGN(struct_sz, KSMBD_DIR_INFO_ALIGNMENT);
39513957
d_info->last_entry_off_align = next_entry_offset - struct_sz;
39523958

0 commit comments

Comments
 (0)