Commit 227c3d54 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents 6fe0be6d c444139c
Loading
Loading
Loading
Loading
+38 −8
Original line number Diff line number Diff line
@@ -540,24 +540,54 @@ int ksmbd_conn_transport_init(void)

static void stop_sessions(void)
{
	struct ksmbd_conn *conn;
	struct ksmbd_conn *conn, *target;
	struct ksmbd_transport *t;
	bool any;
	int bkt;

	/*
	 * Serialised via init_lock; no concurrent stop_sessions() can
	 * touch conn->stop_called, so writing it under the read lock is
	 * safe.
	 */
again:
	target = NULL;
	any = false;
	down_read(&conn_list_lock);
	hash_for_each(conn_list, bkt, conn, hlist) {
		t = conn->transport;
		any = true;
		if (conn->stop_called)
			continue;
		atomic_inc(&conn->refcnt);
		conn->stop_called = true;
		/*
		 * Mark the connection EXITING while still holding the
		 * read lock so the selection and the status transition
		 * happen together.  Do not regress a connection that has
		 * already advanced to RELEASING on its own (e.g. the
		 * handler exited its receive loop for an unrelated
		 * reason).
		 */
		if (READ_ONCE(conn->status) != KSMBD_SESS_RELEASING)
			ksmbd_conn_set_exiting(conn);
		if (t->ops->shutdown) {
		target = conn;
		break;
	}
	up_read(&conn_list_lock);

	if (target) {
		t = target->transport;
		if (t->ops->shutdown)
			t->ops->shutdown(t);
			down_read(&conn_list_lock);
		if (atomic_dec_and_test(&target->refcnt)) {
			ida_destroy(&target->async_ida);
			t->ops->free_transport(t);
			kfree(target);
		}
		goto again;
	}
	up_read(&conn_list_lock);

	if (!hash_empty(conn_list)) {
	if (any) {
		msleep(100);
		goto again;
	}
+1 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ struct ksmbd_conn {
	struct mutex			srv_mutex;
	int				status;
	unsigned int			cli_cap;
	bool				stop_called;
	union {
		__be32			inet_addr;
#if IS_ENABLED(CONFIG_IPV6)
+7 −1
Original line number Diff line number Diff line
@@ -3946,7 +3946,13 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
		goto free_conv_name;
	}

	struct_sz = readdir_info_level_struct_sz(info_level) + conv_len;
	struct_sz = readdir_info_level_struct_sz(info_level);
	if (struct_sz == -EOPNOTSUPP) {
		rc = -EINVAL;
		goto free_conv_name;
	}

	struct_sz += conv_len;
	next_entry_offset = ALIGN(struct_sz, KSMBD_DIR_INFO_ALIGNMENT);
	d_info->last_entry_off_align = next_entry_offset - struct_sz;