Skip to content

Commit bdb65b3

Browse files
committed
smb: client: fix use-after-free of signing key
jira LE-4669 cve CVE-2024-53179 Rebuild_History Non-Buildable kernel-4.18.0-553.82.1.el8_10 commit-author Paulo Alcantara <pc@manguebit.com> commit 343d7fe Empty-Commit: Cherry-Pick Conflicts during history rebuild. Will be included in final tarball splat. Ref for failed cherry-pick at: ciq/ciq_backports/kernel-4.18.0-553.82.1.el8_10/343d7fe6.failed Customers have reported use-after-free in @ses->auth_key.response with SMB2.1 + sign mounts which occurs due to following race: task A task B cifs_mount() dfs_mount_share() get_session() cifs_mount_get_session() cifs_send_recv() cifs_get_smb_ses() compound_send_recv() cifs_setup_session() smb2_setup_request() kfree_sensitive() smb2_calc_signature() crypto_shash_setkey() *UAF* Fix this by ensuring that we have a valid @ses->auth_key.response by checking whether @ses->ses_status is SES_GOOD or SES_EXITING with @ses->ses_lock held. After commit 24a9799 ("smb: client: fix UAF in smb2_reconnect_server()"), we made sure to call ->logoff() only when @SES was known to be good (e.g. valid ->auth_key.response), so it's safe to access signing key when @ses->ses_status == SES_EXITING. Cc: stable@vger.kernel.org Reported-by: Jay Shin <jaeshin@redhat.com> Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com> Signed-off-by: Steve French <stfrench@microsoft.com> (cherry picked from commit 343d7fe) Signed-off-by: Jonathan Maple <jmaple@ciq.com> # Conflicts: # fs/cifs/smb2transport.c
1 parent 4a31687 commit bdb65b3

File tree

1 file changed

+140
-0
lines changed

1 file changed

+140
-0
lines changed
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
smb: client: fix use-after-free of signing key
2+
3+
jira LE-4669
4+
cve CVE-2024-53179
5+
Rebuild_History Non-Buildable kernel-4.18.0-553.82.1.el8_10
6+
commit-author Paulo Alcantara <pc@manguebit.com>
7+
commit 343d7fe6df9e247671440a932b6a73af4fa86d95
8+
Empty-Commit: Cherry-Pick Conflicts during history rebuild.
9+
Will be included in final tarball splat. Ref for failed cherry-pick at:
10+
ciq/ciq_backports/kernel-4.18.0-553.82.1.el8_10/343d7fe6.failed
11+
12+
Customers have reported use-after-free in @ses->auth_key.response with
13+
SMB2.1 + sign mounts which occurs due to following race:
14+
15+
task A task B
16+
cifs_mount()
17+
dfs_mount_share()
18+
get_session()
19+
cifs_mount_get_session() cifs_send_recv()
20+
cifs_get_smb_ses() compound_send_recv()
21+
cifs_setup_session() smb2_setup_request()
22+
kfree_sensitive() smb2_calc_signature()
23+
crypto_shash_setkey() *UAF*
24+
25+
Fix this by ensuring that we have a valid @ses->auth_key.response by
26+
checking whether @ses->ses_status is SES_GOOD or SES_EXITING with
27+
@ses->ses_lock held. After commit 24a9799aa8ef ("smb: client: fix UAF
28+
in smb2_reconnect_server()"), we made sure to call ->logoff() only
29+
when @ses was known to be good (e.g. valid ->auth_key.response), so
30+
it's safe to access signing key when @ses->ses_status == SES_EXITING.
31+
32+
Cc: stable@vger.kernel.org
33+
Reported-by: Jay Shin <jaeshin@redhat.com>
34+
Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
35+
Signed-off-by: Steve French <stfrench@microsoft.com>
36+
(cherry picked from commit 343d7fe6df9e247671440a932b6a73af4fa86d95)
37+
Signed-off-by: Jonathan Maple <jmaple@ciq.com>
38+
39+
# Conflicts:
40+
# fs/cifs/smb2transport.c
41+
diff --cc fs/cifs/smb2transport.c
42+
index c6bf79f874d4,475b36c27f65..000000000000
43+
--- a/fs/cifs/smb2transport.c
44+
+++ b/fs/cifs/smb2transport.c
45+
@@@ -78,13 -74,14 +78,13 @@@ err
46+
47+
48+
static
49+
- int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
50+
+ int smb3_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
51+
{
52+
struct cifs_chan *chan;
53+
- struct TCP_Server_Info *pserver;
54+
struct cifs_ses *ses = NULL;
55+
+ struct TCP_Server_Info *it = NULL;
56+
int i;
57+
int rc = 0;
58+
- bool is_binding = false;
59+
60+
spin_lock(&cifs_tcp_ses_lock);
61+
62+
@@@ -225,16 -261,16 +250,30 @@@ smb2_calc_signature(struct smb_rqst *rq
63+
unsigned char *sigptr = smb2_signature;
64+
struct kvec *iov = rqst->rq_iov;
65+
struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base;
66+
++<<<<<<< HEAD:fs/cifs/smb2transport.c
67+
+ struct cifs_ses *ses;
68+
+ struct shash_desc *shash;
69+
+ struct crypto_shash *hash;
70+
+ struct sdesc *sdesc = NULL;
71+
++=======
72+
+ struct shash_desc *shash = NULL;
73+
++>>>>>>> 343d7fe6df9e (smb: client: fix use-after-free of signing key):fs/smb/client/smb2transport.c
74+
struct smb_rqst drqst;
75+
+ __u64 sid = le64_to_cpu(shdr->SessionId);
76+
+ u8 key[SMB2_NTLMV2_SESSKEY_SIZE];
77+
78+
++<<<<<<< HEAD:fs/cifs/smb2transport.c
79+
+ ses = smb2_find_smb_ses(server, le64_to_cpu(shdr->SessionId));
80+
+ if (unlikely(!ses)) {
81+
+ cifs_server_dbg(VFS, "%s: Could not find session\n", __func__);
82+
+ return -ENOENT;
83+
++=======
84+
+ rc = smb2_get_sign_key(server, sid, key);
85+
+ if (unlikely(rc)) {
86+
+ cifs_server_dbg(FYI, "%s: [sesid=0x%llx] couldn't find signing key: %d\n",
87+
+ __func__, sid, rc);
88+
+ return rc;
89+
++>>>>>>> 343d7fe6df9e (smb: client: fix use-after-free of signing key):fs/smb/client/smb2transport.c
90+
}
91+
92+
memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
93+
@@@ -247,14 -283,11 +286,18 @@@
94+
"%s: sha256 alloc failed\n", __func__);
95+
goto out;
96+
}
97+
+ shash = &sdesc->shash;
98+
} else {
99+
- shash = server->secmech.hmacsha256;
100+
+ hash = server->secmech.hmacsha256;
101+
+ shash = &server->secmech.sdeschmacsha256->shash;
102+
}
103+
104+
++<<<<<<< HEAD:fs/cifs/smb2transport.c
105+
+ rc = crypto_shash_setkey(hash, ses->auth_key.response,
106+
+ SMB2_NTLMV2_SESSKEY_SIZE);
107+
++=======
108+
+ rc = crypto_shash_setkey(shash->tfm, key, sizeof(key));
109+
++>>>>>>> 343d7fe6df9e (smb: client: fix use-after-free of signing key):fs/smb/client/smb2transport.c
110+
if (rc) {
111+
cifs_server_dbg(VFS,
112+
"%s: Could not update with response\n",
113+
@@@ -295,9 -328,7 +338,13 @@@
114+
115+
out:
116+
if (allocate_crypto)
117+
++<<<<<<< HEAD:fs/cifs/smb2transport.c
118+
+ cifs_free_hash(&hash, &sdesc);
119+
+ if (ses)
120+
+ cifs_put_smb_ses(ses);
121+
++=======
122+
+ cifs_free_hash(&shash);
123+
++>>>>>>> 343d7fe6df9e (smb: client: fix use-after-free of signing key):fs/smb/client/smb2transport.c
124+
return rc;
125+
}
126+
127+
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
128+
index 7fe6780e742d..fa38497d7d67 100644
129+
--- a/fs/cifs/smb2proto.h
130+
+++ b/fs/cifs/smb2proto.h
131+
@@ -37,8 +37,6 @@ extern struct mid_q_entry *smb2_setup_request(struct cifs_ses *ses,
132+
struct smb_rqst *rqst);
133+
extern struct mid_q_entry *smb2_setup_async_request(
134+
struct TCP_Server_Info *server, struct smb_rqst *rqst);
135+
-extern struct cifs_ses *smb2_find_smb_ses(struct TCP_Server_Info *server,
136+
- __u64 ses_id);
137+
extern struct cifs_tcon *smb2_find_smb_tcon(struct TCP_Server_Info *server,
138+
__u64 ses_id, __u32 tid);
139+
extern int smb2_calc_signature(struct smb_rqst *rqst,
140+
* Unmerged path fs/cifs/smb2transport.c

0 commit comments

Comments
 (0)