CVE-2026-45972
Description
In the Linux kernel, the following vulnerability has been resolved:
smb: client: fix potential UAF and double free in smb2_open_file()
Zero out @err_iov and @err_buftype before retrying SMB2_open() to prevent an UAF bug if @data != NULL, otherwise a double free.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
A use-after-free and double free vulnerability in Linux kernel's smb2_open_file() could lead to memory corruption.
Vulnerability
In the Linux kernel's CIFS/SMB2 client, the function smb2_open_file() does not zero out @err_iov and @err_buftype before retrying SMB2_open(). This omission can lead to a use-after-free (UAF) bug when @data is not NULL, and a double free in other cases. Affected versions include Linux kernel releases that contain this code. The fix was introduced in commit [1].
Exploitation
An attacker with the ability to trigger a retry of SMB2_open() on a corrupted or maliciously crafted file system could potentially exploit this race condition. The vulnerability requires the attacker to have access to the SMB2 client and cause the retry path to be executed.
Impact
Successful exploitation could lead to memory corruption, potentially resulting in a denial of service or, in some cases, arbitrary code execution due to the double free or UAF. The exact privileges depend on the context of the executing process.
Mitigation
The vulnerability is fixed in the Linux kernel by commit e66dcf7bb9c4df5582c82bc3582725abcbfbea73. Users should apply the patch to their kernels. There is no known workaround; updating to a patched version is required.
AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1Patches
12ebbbc4bfad4csmb: client: fix potential UAF and double free in smb2_open_file()
1 file changed · +2 −1
fs/smb/client/smb2file.c+2 −1 modifieddiff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c index 2dd08388ea8733..1f7f284a784496 100644 --- a/fs/smb/client/smb2file.c +++ b/fs/smb/client/smb2file.c @@ -179,6 +179,8 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, &err_buftype); if (rc == -EACCES && retry_without_read_attributes) { free_rsp_buf(err_buftype, err_iov.iov_base); + memset(&err_iov, 0, sizeof(err_iov)); + err_buftype = CIFS_NO_BUFFER; oparms->desired_access &= ~FILE_READ_ATTRIBUTES; rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, &err_buftype); -- cgit 1.3-korg
e66dcf7bb9c4smb: client: fix potential UAF and double free in smb2_open_file()
1 file changed · +2 −1
fs/smb/client/smb2file.c+2 −1 modifieddiff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c index 03f90553d8319e..e6cdf2efc7f4f4 100644 --- a/fs/smb/client/smb2file.c +++ b/fs/smb/client/smb2file.c @@ -178,6 +178,8 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 &err_buftype); if (rc == -EACCES && retry_without_read_attributes) { free_rsp_buf(err_buftype, err_iov.iov_base); + memset(&err_iov, 0, sizeof(err_iov)); + err_buftype = CIFS_NO_BUFFER; oparms->desired_access &= ~FILE_READ_ATTRIBUTES; rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, &err_buftype); -- cgit 1.3-korg
639deb962986smb: client: fix potential UAF and double free in smb2_open_file()
1 file changed · +2 −1
fs/smb/client/smb2file.c+2 −1 modifieddiff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c index 2dd08388ea8733..1f7f284a784496 100644 --- a/fs/smb/client/smb2file.c +++ b/fs/smb/client/smb2file.c @@ -179,6 +179,8 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, &err_buftype); if (rc == -EACCES && retry_without_read_attributes) { free_rsp_buf(err_buftype, err_iov.iov_base); + memset(&err_iov, 0, sizeof(err_iov)); + err_buftype = CIFS_NO_BUFFER; oparms->desired_access &= ~FILE_READ_ATTRIBUTES; rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, &err_buftype); -- cgit 1.3-korg
96e53bb3ee2fsmb: client: fix potential UAF and double free in smb2_open_file()
1 file changed · +2 −1
fs/smb/client/smb2file.c+2 −1 modifieddiff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c index 7fc7fcabce80c7..fe016144f3405e 100644 --- a/fs/smb/client/smb2file.c +++ b/fs/smb/client/smb2file.c @@ -124,6 +124,8 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 &err_buftype); if (rc == -EACCES && retry_without_read_attributes) { free_rsp_buf(err_buftype, err_iov.iov_base); + memset(&err_iov, 0, sizeof(err_iov)); + err_buftype = CIFS_NO_BUFFER; oparms->desired_access &= ~FILE_READ_ATTRIBUTES; rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, &err_buftype); -- cgit 1.3-korg
7425453ea16dsmb: client: fix potential UAF and double free in smb2_open_file()
1 file changed · +2 −1
fs/smb/client/smb2file.c+2 −1 modifieddiff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c index d436057ed77e32..4e7d5c612256d6 100644 --- a/fs/smb/client/smb2file.c +++ b/fs/smb/client/smb2file.c @@ -123,6 +123,8 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 &err_buftype); if (rc == -EACCES && retry_without_read_attributes) { free_rsp_buf(err_buftype, err_iov.iov_base); + memset(&err_iov, 0, sizeof(err_iov)); + err_buftype = CIFS_NO_BUFFER; oparms->desired_access &= ~FILE_READ_ATTRIBUTES; rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, &err_buftype); -- cgit 1.3-korg
4d339b219004smb: client: fix potential UAF and double free in smb2_open_file()
1 file changed · +2 −1
fs/smb/client/smb2file.c+2 −1 modifieddiff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c index 414242a33d61ac..b7ab18d4bedcaa 100644 --- a/fs/smb/client/smb2file.c +++ b/fs/smb/client/smb2file.c @@ -123,6 +123,8 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 &err_buftype); if (rc == -EACCES && retry_without_read_attributes) { free_rsp_buf(err_buftype, err_iov.iov_base); + memset(&err_iov, 0, sizeof(err_iov)); + err_buftype = CIFS_NO_BUFFER; oparms->desired_access &= ~FILE_READ_ATTRIBUTES; rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, &err_buftype); -- cgit 1.3-korg
639deb962986smb: client: fix potential UAF and double free in smb2_open_file()
1 file changed · +2 −1
fs/smb/client/smb2file.c+2 −1 modifieddiff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c index 2dd08388ea8733..1f7f284a784496 100644 --- a/fs/smb/client/smb2file.c +++ b/fs/smb/client/smb2file.c @@ -179,6 +179,8 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, &err_buftype); if (rc == -EACCES && retry_without_read_attributes) { free_rsp_buf(err_buftype, err_iov.iov_base); + memset(&err_iov, 0, sizeof(err_iov)); + err_buftype = CIFS_NO_BUFFER; oparms->desired_access &= ~FILE_READ_ATTRIBUTES; rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, &err_buftype); -- cgit 1.3-korg
7425453ea16dsmb: client: fix potential UAF and double free in smb2_open_file()
1 file changed · +2 −1
fs/smb/client/smb2file.c+2 −1 modifieddiff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c index d436057ed77e32..4e7d5c612256d6 100644 --- a/fs/smb/client/smb2file.c +++ b/fs/smb/client/smb2file.c @@ -123,6 +123,8 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 &err_buftype); if (rc == -EACCES && retry_without_read_attributes) { free_rsp_buf(err_buftype, err_iov.iov_base); + memset(&err_iov, 0, sizeof(err_iov)); + err_buftype = CIFS_NO_BUFFER; oparms->desired_access &= ~FILE_READ_ATTRIBUTES; rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, &err_buftype); -- cgit 1.3-korg
96e53bb3ee2fsmb: client: fix potential UAF and double free in smb2_open_file()
1 file changed · +2 −1
fs/smb/client/smb2file.c+2 −1 modifieddiff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c index 7fc7fcabce80c7..fe016144f3405e 100644 --- a/fs/smb/client/smb2file.c +++ b/fs/smb/client/smb2file.c @@ -124,6 +124,8 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 &err_buftype); if (rc == -EACCES && retry_without_read_attributes) { free_rsp_buf(err_buftype, err_iov.iov_base); + memset(&err_iov, 0, sizeof(err_iov)); + err_buftype = CIFS_NO_BUFFER; oparms->desired_access &= ~FILE_READ_ATTRIBUTES; rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, &err_buftype); -- cgit 1.3-korg
4d339b219004smb: client: fix potential UAF and double free in smb2_open_file()
1 file changed · +2 −1
fs/smb/client/smb2file.c+2 −1 modifieddiff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c index 414242a33d61ac..b7ab18d4bedcaa 100644 --- a/fs/smb/client/smb2file.c +++ b/fs/smb/client/smb2file.c @@ -123,6 +123,8 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 &err_buftype); if (rc == -EACCES && retry_without_read_attributes) { free_rsp_buf(err_buftype, err_iov.iov_base); + memset(&err_iov, 0, sizeof(err_iov)); + err_buftype = CIFS_NO_BUFFER; oparms->desired_access &= ~FILE_READ_ATTRIBUTES; rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, &err_buftype); -- cgit 1.3-korg
e66dcf7bb9c4smb: client: fix potential UAF and double free in smb2_open_file()
1 file changed · +2 −1
fs/smb/client/smb2file.c+2 −1 modifieddiff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c index 03f90553d8319e..e6cdf2efc7f4f4 100644 --- a/fs/smb/client/smb2file.c +++ b/fs/smb/client/smb2file.c @@ -178,6 +178,8 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 &err_buftype); if (rc == -EACCES && retry_without_read_attributes) { free_rsp_buf(err_buftype, err_iov.iov_base); + memset(&err_iov, 0, sizeof(err_iov)); + err_buftype = CIFS_NO_BUFFER; oparms->desired_access &= ~FILE_READ_ATTRIBUTES; rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, &err_buftype); -- cgit 1.3-korg
ebbbc4bfad4csmb: client: fix potential UAF and double free in smb2_open_file()
1 file changed · +2 −1
fs/smb/client/smb2file.c+2 −1 modifieddiff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c index 2dd08388ea8733..1f7f284a784496 100644 --- a/fs/smb/client/smb2file.c +++ b/fs/smb/client/smb2file.c @@ -179,6 +179,8 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, &err_buftype); if (rc == -EACCES && retry_without_read_attributes) { free_rsp_buf(err_buftype, err_iov.iov_base); + memset(&err_iov, 0, sizeof(err_iov)); + err_buftype = CIFS_NO_BUFFER; oparms->desired_access &= ~FILE_READ_ATTRIBUTES; rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov, &err_buftype); -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Missing cleanup of err_iov and err_buftype before retrying SMB2_open() allows stale pointers to be reused, leading to use-after-free or double free."
Attack vector
An attacker on the SMB server can trigger this bug by causing the initial `SMB2_open()` call to fail with `-EACCES` while also populating `err_iov` with a non-NULL `iov_base` (i.e., `@data != NULL`). When the client retries the open with reduced access, the stale `err_iov.iov_base` pointer from the first call is still present. If the second `SMB2_open()` call also writes into `err_iov`, the old pointer is overwritten without being freed, leading to a memory leak; conversely, if the second call fails and the caller later frees `err_iov.iov_base`, the same pointer may be freed twice (double free) or used after being freed (UAF) [patch_id=2660835].
Affected code
The vulnerability is in `fs/smb/client/smb2file.c` in the `smb2_open_file()` function [patch_id=2660835]. The fault lies in the retry path when `SMB2_open()` returns `-EACCES` and `retry_without_read_attributes` is true: after calling `free_rsp_buf()` on the previous response, the code reuses `err_iov` and `err_buftype` without resetting them before the second `SMB2_open()` call.
What the fix does
The patch adds two lines after `free_rsp_buf()` in the retry path: `memset(&err_iov, 0, sizeof(err_iov))` zeroes the iovec structure, and `err_buftype = CIFS_NO_BUFFER` resets the buffer type indicator [patch_id=2660835]. This ensures that the second `SMB2_open()` call starts with clean state, preventing the stale pointer from being misinterpreted as an already-allocated buffer. The fix closes both the use-after-free scenario (where the old pointer could be read after being freed) and the double-free scenario (where the same pointer could be freed again on a subsequent error path).
Preconditions
- networkThe SMB server must respond to the initial SMB2_open() request with -EACCES and supply a response buffer that populates err_iov.iov_base.
- configThe client must have retry_without_read_attributes enabled (default behavior when FILE_READ_ATTRIBUTES is in desired_access).
Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- git.kernel.org/stable/c/4d339b219004869e96c4ce56b8891f83a38da4c0nvd
- git.kernel.org/stable/c/639deb962986ef2f5e2a6d5a600c66f922471e81nvd
- git.kernel.org/stable/c/7425453ea16dbc3bbb0f6cac4d60b537e5e4d151nvd
- git.kernel.org/stable/c/96e53bb3ee2f354cf6b4ab07bcc56e500f8b3f74nvd
- git.kernel.org/stable/c/e66dcf7bb9c4df5582c82bc3582725abcbfbea73nvd
- git.kernel.org/stable/c/ebbbc4bfad4cb355d17c671223d0814ee3ef4edanvd
News mentions
0No linked articles in our index yet.