From patchwork Tue Feb 6 17:49:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bethany Jamison X-Patchwork-Id: 1895866 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4TTrNY0bZmz23gM for ; Wed, 7 Feb 2024 04:49:33 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1rXPZW-0005NS-Bn; Tue, 06 Feb 2024 17:49:26 +0000 Received: from smtp-relay-internal-0.internal ([10.131.114.225] helo=smtp-relay-internal-0.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1rXPZS-0005Mc-8d for kernel-team@lists.ubuntu.com; Tue, 06 Feb 2024 17:49:22 +0000 Received: from mail-qt1-f198.google.com (mail-qt1-f198.google.com [209.85.160.198]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-0.canonical.com (Postfix) with ESMTPS id 223BF3F15F for ; Tue, 6 Feb 2024 17:49:21 +0000 (UTC) Received: by mail-qt1-f198.google.com with SMTP id d75a77b69052e-427b56e96a6so83056941cf.3 for ; Tue, 06 Feb 2024 09:49:21 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707241760; x=1707846560; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Phgt7SaDujdbvA1FU9e64TVQRl3QABA8cbEHcRrH4Y4=; b=pREhL2WYGw67U4QGEjDb3yCkBx++fR4PgVik4Nx3LtLje1IEgUnrOWJsr9fAvV5ZZn v6hqPEN2v5uMtFjWFhBynST8saq+KcRCoo06G+ZDQtSwzn9Tjhs3Hhu1gj/8ZvDJHMjG CiiqLt8Xg8NAt8X067HIDRD1p0yS9oGnTOLPlAzvKOj5OCca+3ILMDv5iNj9IgXKG7Xt UE9WoyDdbBZqsCB2bA2id5TeMg72Uc6r1ICm9iGoRIUjlZRltIvxWSpT57hzwbggQyl5 KubBoKDpf++Da0dx324oaG6nhvVW7cY+Rnfeqd5s/1ul7+9w/lW0/IzusUK/M/ve6BJ5 x5FA== X-Gm-Message-State: AOJu0YxxsqKCI01pa57Vj7T8dzMAbfjns3FW3iJ19qm+T/U4uVk1FfhK HTkJuQ3O6ZKKdPlEu/IVeU+SmM5RC/rd2fJcWF2EMXJOt76hhrh90DNOKVG1uE91n4/gJwBUBW5 2tFzwznlsuKKf/Wtw32/a+ywbhMmNXuLaYkgHFqYFOozuogIugpiB9x0lCchojFCsIXtmtCMi9z zxCdaSV7Aipw== X-Received: by 2002:ac8:7f46:0:b0:42a:7254:83ea with SMTP id g6-20020ac87f46000000b0042a725483eamr3494046qtk.41.1707241759819; Tue, 06 Feb 2024 09:49:19 -0800 (PST) X-Google-Smtp-Source: AGHT+IE5yQAMhVBwA7nu8xiNCvJ4RsPSRlkwyhSPKlWTf18QkJj6h2VCpGIQd/iV9FYpTAtHWZVkfQ== X-Received: by 2002:ac8:7f46:0:b0:42a:7254:83ea with SMTP id g6-20020ac87f46000000b0042a725483eamr3494029qtk.41.1707241759404; Tue, 06 Feb 2024 09:49:19 -0800 (PST) Received: from smtp.gmail.com (104-218-69-129.dynamic.lnk.ne.allofiber.net. [104.218.69.129]) by smtp.gmail.com with ESMTPSA id ic14-20020a05622a68ce00b0042c25a4c3b6sm1082117qtb.58.2024.02.06.09.49.18 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Feb 2024 09:49:19 -0800 (PST) From: Bethany Jamison To: kernel-team@lists.ubuntu.com Subject: [SRU][Jammy][PATCH 1/1] ksmbd: destroy expired sessions Date: Tue, 6 Feb 2024 11:49:17 -0600 Message-Id: <20240206174917.14714-2-bethany.jamison@canonical.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240206174917.14714-1-bethany.jamison@canonical.com> References: <20240206174917.14714-1-bethany.jamison@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Namjae Jeon client can indefinitely send smb2 session setup requests with the SessionId set to 0, thus indefinitely spawning new sessions, and causing indefinite memory usage. This patch limit to the number of sessions using expired timeout and session state. Cc: stable@vger.kernel.org Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-20478 Signed-off-by: Namjae Jeon Signed-off-by: Steve French (backported from commit ea174a91893956450510945a0c5d1a10b5323656) [bjamison: Jammy code structure was different in smb2pdu.h than upstream - found relevant code chunk and implemented fix commit's intended change] CVE-2023-32247 Signed-off-by: Bethany Jamison --- fs/ksmbd/mgmt/user_session.c | 68 ++++++++++++++++++++---------------- fs/ksmbd/mgmt/user_session.h | 1 + fs/ksmbd/smb2pdu.c | 1 + fs/ksmbd/smb2pdu.h | 2 ++ 4 files changed, 41 insertions(+), 31 deletions(-) diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c index 69b85a98e2c35..b809f7987b9f4 100644 --- a/fs/ksmbd/mgmt/user_session.c +++ b/fs/ksmbd/mgmt/user_session.c @@ -174,70 +174,73 @@ static struct ksmbd_session *__session_lookup(unsigned long long id) struct ksmbd_session *sess; hash_for_each_possible(sessions_table, sess, hlist, id) { - if (id == sess->id) + if (id == sess->id) { + sess->last_active = jiffies; return sess; + } } return NULL; } +static void ksmbd_expire_session(struct ksmbd_conn *conn) +{ + unsigned long id; + struct ksmbd_session *sess; + + 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); + ksmbd_session_destroy(sess); + continue; + } + } +} + int ksmbd_session_register(struct ksmbd_conn *conn, struct ksmbd_session *sess) { sess->dialect = conn->dialect; memcpy(sess->ClientGUID, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE); + ksmbd_expire_session(conn); return xa_err(xa_store(&conn->sessions, sess->id, sess, GFP_KERNEL)); } -static int ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess) +static void 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 -ENOENT; + return; kfree(chann); - - return 0; } void ksmbd_sessions_deregister(struct ksmbd_conn *conn) { struct ksmbd_session *sess; + unsigned long id; - if (conn->binding) { - int bkt; - - down_write(&sessions_table_lock); - hash_for_each(sessions_table, bkt, sess, hlist) { - if (!ksmbd_chann_del(conn, sess)) { - up_write(&sessions_table_lock); - goto sess_destroy; - } + xa_for_each(&conn->sessions, id, sess) { + ksmbd_chann_del(conn, sess); + if (xa_empty(&sess->ksmbd_chann_list)) { + xa_erase(&conn->sessions, sess->id); + ksmbd_session_destroy(sess); } - up_write(&sessions_table_lock); - } else { - unsigned long id; - - xa_for_each(&conn->sessions, id, sess) { - if (!ksmbd_chann_del(conn, sess)) - goto sess_destroy; - } - } - - return; - -sess_destroy: - if (xa_empty(&sess->ksmbd_chann_list)) { - xa_erase(&conn->sessions, sess->id); - ksmbd_session_destroy(sess); } } struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn, unsigned long long id) { - return xa_load(&conn->sessions, id); + struct ksmbd_session *sess; + + sess = xa_load(&conn->sessions, id); + if (sess) + sess->last_active = jiffies; + return sess; } struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id) @@ -246,6 +249,8 @@ struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id) down_read(&sessions_table_lock); sess = __session_lookup(id); + if (sess) + sess->last_active = jiffies; up_read(&sessions_table_lock); return sess; @@ -324,6 +329,7 @@ static struct ksmbd_session *__session_create(int protocol) if (ksmbd_init_file_table(&sess->file_table)) goto error; + sess->last_active = jiffies; sess->state = SMB2_SESSION_IN_PROGRESS; set_session_flag(sess, protocol); xa_init(&sess->tree_conns); diff --git a/fs/ksmbd/mgmt/user_session.h b/fs/ksmbd/mgmt/user_session.h index 44a3c67b2bd92..51f38e5b61abb 100644 --- a/fs/ksmbd/mgmt/user_session.h +++ b/fs/ksmbd/mgmt/user_session.h @@ -59,6 +59,7 @@ struct ksmbd_session { __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE]; struct ksmbd_file_table file_table; + unsigned long last_active; }; static inline int test_session_flag(struct ksmbd_session *sess, int bit) diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 8f438a3f3d0bb..89af3a6b8fb75 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -1895,6 +1895,7 @@ int smb2_sess_setup(struct ksmbd_work *work) if (sess->user && sess->user->flags & KSMBD_USER_FLAG_DELAY_SESSION) try_delay = true; + sess->last_active = jiffies; sess->state = SMB2_SESSION_EXPIRED; if (try_delay) ssleep(5); diff --git a/fs/ksmbd/smb2pdu.h b/fs/ksmbd/smb2pdu.h index fa1cd556ab7ac..ef254243a7359 100644 --- a/fs/ksmbd/smb2pdu.h +++ b/fs/ksmbd/smb2pdu.h @@ -376,6 +376,8 @@ struct smb2_negotiate_rsp { #define SMB2_SESSION_IN_PROGRESS BIT(0) #define SMB2_SESSION_VALID BIT(1) +#define SMB2_SESSION_TIMEOUT (10 * HZ) + /* Flags */ #define SMB2_SESSION_REQ_FLAG_BINDING 0x01 #define SMB2_SESSION_REQ_FLAG_ENCRYPT_DATA 0x04