Unverified Commit 217a0aae authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!2476 Fixed five CVEs vulnerabilities of ksmbd

Merge Pull Request from: @ci-robot 
 
PR sync from: ZhaoLong Wang <wangzhaolong1@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/ZN7CBBIOC34QBBU3KJU6GKB33UJPAFIN/ 
CVE-2023-32254
CVE-2023-32246
CVE-2023-32256
CVE-2023-32258
CVE-2023-2593

Marios Makassikis (2):
  ksmbd: send proper error response in smb2_tree_connect()

Namjae Jeon (4):
  ksmbd: fix racy issue under cocurrent smb2 tree disconnect
  ksmbd: call rcu_barrier() in ksmbd_server_exit()
  ksmbd: fix racy issue from smb2 close and logoff with multichannel
  ksmbd: fix infinite loop in ksmbd_conn_handler_loop()


-- 
2.34.3
 
https://gitee.com/src-openeuler/kernel/issues/I74FNG
https://gitee.com/src-openeuler/kernel/issues/I74FJA
https://gitee.com/src-openeuler/kernel/issues/I7BIK2
https://gitee.com/src-openeuler/kernel/issues/I74FIB 
 
Link:https://gitee.com/openeuler/kernel/pulls/2476

 

Reviewed-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents e220ebed b2191bd6
Loading
Loading
Loading
Loading
+42 −14
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ static DEFINE_MUTEX(init_lock);
static struct ksmbd_conn_ops default_conn_ops;

LIST_HEAD(conn_list);
DEFINE_RWLOCK(conn_list_lock);
DECLARE_RWSEM(conn_list_lock);

/**
 * ksmbd_conn_free() - free resources of the connection instance
@@ -32,9 +32,9 @@ DEFINE_RWLOCK(conn_list_lock);
 */
void ksmbd_conn_free(struct ksmbd_conn *conn)
{
	write_lock(&conn_list_lock);
	down_write(&conn_list_lock);
	list_del(&conn->conns_list);
	write_unlock(&conn_list_lock);
	up_write(&conn_list_lock);

	xa_destroy(&conn->sessions);
	kvfree(conn->request_buf);
@@ -78,9 +78,9 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
	spin_lock_init(&conn->llist_lock);
	INIT_LIST_HEAD(&conn->lock_list);

	write_lock(&conn_list_lock);
	down_write(&conn_list_lock);
	list_add(&conn->conns_list, &conn_list);
	write_unlock(&conn_list_lock);
	up_write(&conn_list_lock);
	return conn;
}

@@ -89,7 +89,7 @@ bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c)
	struct ksmbd_conn *t;
	bool ret = false;

	read_lock(&conn_list_lock);
	down_read(&conn_list_lock);
	list_for_each_entry(t, &conn_list, conns_list) {
		if (memcmp(t->ClientGUID, c->ClientGUID, SMB2_CLIENT_GUID_SIZE))
			continue;
@@ -97,7 +97,7 @@ bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c)
		ret = true;
		break;
	}
	read_unlock(&conn_list_lock);
	up_read(&conn_list_lock);
	return ret;
}

@@ -153,9 +153,37 @@ void ksmbd_conn_unlock(struct ksmbd_conn *conn)
	mutex_unlock(&conn->srv_mutex);
}

void ksmbd_conn_wait_idle(struct ksmbd_conn *conn)
void ksmbd_all_conn_set_status(u64 sess_id, u32 status)
{
	struct ksmbd_conn *conn;

	down_read(&conn_list_lock);
	list_for_each_entry(conn, &conn_list, conns_list) {
		if (conn->binding || xa_load(&conn->sessions, sess_id))
			WRITE_ONCE(conn->status, status);
	}
	up_read(&conn_list_lock);
}

void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id)
{
	struct ksmbd_conn *bind_conn;

	wait_event(conn->req_running_q, atomic_read(&conn->req_running) < 2);

	down_read(&conn_list_lock);
	list_for_each_entry(bind_conn, &conn_list, conns_list) {
		if (bind_conn == conn)
			continue;

		if ((bind_conn->binding || xa_load(&bind_conn->sessions, sess_id)) &&
		    !ksmbd_conn_releasing(bind_conn) &&
		    atomic_read(&bind_conn->req_running)) {
			wait_event(bind_conn->req_running_q,
				atomic_read(&bind_conn->req_running) == 0);
		}
	}
	up_read(&conn_list_lock);
}

int ksmbd_conn_write(struct ksmbd_work *work)
@@ -326,7 +354,7 @@ int ksmbd_conn_handler_loop(void *p)
		size = pdu_size + 4 + 1;
		conn->request_buf = kvmalloc(size, GFP_KERNEL);
		if (!conn->request_buf)
			continue;
			break;

		memcpy(conn->request_buf, hdr_buf, sizeof(hdr_buf));

@@ -361,10 +389,10 @@ int ksmbd_conn_handler_loop(void *p)
	}

out:
	ksmbd_conn_set_releasing(conn);
	/* Wait till all reference dropped to the Server object*/
	wait_event(conn->r_count_q, atomic_read(&conn->r_count) == 0);


	unload_nls(conn->local_nls);
	if (default_conn_ops.terminate_fn)
		default_conn_ops.terminate_fn(conn);
@@ -406,7 +434,7 @@ static void stop_sessions(void)
	struct ksmbd_transport *t;

again:
	read_lock(&conn_list_lock);
	down_read(&conn_list_lock);
	list_for_each_entry(conn, &conn_list, conns_list) {
		struct task_struct *task;

@@ -417,12 +445,12 @@ static void stop_sessions(void)
				    task->comm, task_pid_nr(task));
		ksmbd_conn_set_exiting(conn);
		if (t->ops->shutdown) {
			read_unlock(&conn_list_lock);
			up_read(&conn_list_lock);
			t->ops->shutdown(t);
			read_lock(&conn_list_lock);
			down_read(&conn_list_lock);
		}
	}
	read_unlock(&conn_list_lock);
	up_read(&conn_list_lock);

	if (!list_empty(&conn_list)) {
		schedule_timeout_interruptible(HZ / 10); /* 100ms */
+16 −3
Original line number Diff line number Diff line
@@ -25,7 +25,8 @@ enum {
	KSMBD_SESS_GOOD,
	KSMBD_SESS_EXITING,
	KSMBD_SESS_NEED_RECONNECT,
	KSMBD_SESS_NEED_NEGOTIATE
	KSMBD_SESS_NEED_NEGOTIATE,
	KSMBD_SESS_RELEASING
};

struct ksmbd_stats {
@@ -134,10 +135,10 @@ struct ksmbd_transport {
#define KSMBD_TCP_PEER_SOCKADDR(c)	((struct sockaddr *)&((c)->peer_addr))

extern struct list_head conn_list;
extern rwlock_t conn_list_lock;
extern struct rw_semaphore conn_list_lock;

bool ksmbd_conn_alive(struct ksmbd_conn *conn);
void ksmbd_conn_wait_idle(struct ksmbd_conn *conn);
void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id);
struct ksmbd_conn *ksmbd_conn_alloc(void);
void ksmbd_conn_free(struct ksmbd_conn *conn);
bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c);
@@ -183,6 +184,11 @@ static inline bool ksmbd_conn_exiting(struct ksmbd_conn *conn)
	return READ_ONCE(conn->status) == KSMBD_SESS_EXITING;
}

static inline bool ksmbd_conn_releasing(struct ksmbd_conn *conn)
{
	return READ_ONCE(conn->status) == KSMBD_SESS_RELEASING;
}

static inline void ksmbd_conn_set_new(struct ksmbd_conn *conn)
{
	WRITE_ONCE(conn->status, KSMBD_SESS_NEW);
@@ -207,4 +213,11 @@ static inline void ksmbd_conn_set_exiting(struct ksmbd_conn *conn)
{
	WRITE_ONCE(conn->status, KSMBD_SESS_EXITING);
}

static inline void ksmbd_conn_set_releasing(struct ksmbd_conn *conn)
{
	WRITE_ONCE(conn->status, KSMBD_SESS_RELEASING);
}

void ksmbd_all_conn_set_status(u64 sess_id, u32 status);
#endif /* __CONNECTION_H__ */
+12 −1
Original line number Diff line number Diff line
@@ -95,7 +95,15 @@ int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
struct ksmbd_tree_connect *ksmbd_tree_conn_lookup(struct ksmbd_session *sess,
						  unsigned int id)
{
	return xa_load(&sess->tree_conns, id);
	struct ksmbd_tree_connect *tcon;

	tcon = xa_load(&sess->tree_conns, id);
	if (tcon) {
		if (test_bit(TREE_CONN_EXPIRE, &tcon->status))
			tcon = NULL;
	}

	return tcon;
}

struct ksmbd_share_config *ksmbd_tree_conn_share(struct ksmbd_session *sess,
@@ -115,6 +123,9 @@ int ksmbd_tree_conn_session_logoff(struct ksmbd_session *sess)
	struct ksmbd_tree_connect *tc;
	unsigned long id;

	if (!sess)
		return -EINVAL;

	xa_for_each(&sess->tree_conns, id, tc)
		ret |= ksmbd_tree_conn_disconnect(sess, tc);
	xa_destroy(&sess->tree_conns);
+3 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@ struct ksmbd_share_config;
struct ksmbd_user;
struct ksmbd_conn;

#define TREE_CONN_EXPIRE		1

struct ksmbd_tree_connect {
	int				id;

@@ -25,6 +27,7 @@ struct ksmbd_tree_connect {

	int				maximal_access;
	bool				posix_extensions;
	unsigned long			status;
};

struct ksmbd_tree_conn_status {
+30 −6
Original line number Diff line number Diff line
@@ -151,10 +151,6 @@ void ksmbd_session_destroy(struct ksmbd_session *sess)
	if (!sess)
		return;

	down_write(&sessions_table_lock);
	hash_del(&sess->hlist);
	up_write(&sessions_table_lock);

	if (sess->user)
		ksmbd_free_user(sess->user);

@@ -185,15 +181,18 @@ static void ksmbd_expire_session(struct ksmbd_conn *conn)
	unsigned long id;
	struct ksmbd_session *sess;

	down_write(&sessions_table_lock);
	xa_for_each(&conn->sessions, id, sess) {
		if (sess->state != SMB2_SESSION_VALID ||
		    time_after(jiffies,
			       sess->last_active + SMB2_SESSION_TIMEOUT)) {
			xa_erase(&conn->sessions, sess->id);
			hash_del(&sess->hlist);
			ksmbd_session_destroy(sess);
			continue;
		}
	}
	up_write(&sessions_table_lock);
}

int ksmbd_session_register(struct ksmbd_conn *conn,
@@ -205,15 +204,16 @@ int ksmbd_session_register(struct ksmbd_conn *conn,
	return xa_err(xa_store(&conn->sessions, sess->id, sess, GFP_KERNEL));
}

static void ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess)
static int ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess)
{
	struct channel *chann;

	chann = xa_erase(&sess->ksmbd_chann_list, (long)conn);
	if (!chann)
		return;
		return -ENOENT;

	kfree(chann);
	return 0;
}

void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
@@ -221,13 +221,37 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
	struct ksmbd_session *sess;
	unsigned long id;

	down_write(&sessions_table_lock);
	if (conn->binding) {
		int bkt;
		struct hlist_node *tmp;

		hash_for_each_safe(sessions_table, bkt, tmp, sess, hlist) {
			if (!ksmbd_chann_del(conn, sess) &&
			    xa_empty(&sess->ksmbd_chann_list)) {
				hash_del(&sess->hlist);
				ksmbd_session_destroy(sess);
			}
		}
	}

	xa_for_each(&conn->sessions, id, sess) {
		unsigned long chann_id;
		struct channel *chann;

		xa_for_each(&sess->ksmbd_chann_list, chann_id, chann) {
			if (chann->conn != conn)
				ksmbd_conn_set_exiting(chann->conn);
		}

		ksmbd_chann_del(conn, sess);
		if (xa_empty(&sess->ksmbd_chann_list)) {
			xa_erase(&conn->sessions, sess->id);
			hash_del(&sess->hlist);
			ksmbd_session_destroy(sess);
		}
	}
	up_write(&sessions_table_lock);
}

struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
Loading