VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-46064

CVE-2026-46064

Description

In the Linux kernel, the following vulnerability has been resolved:

ibmasm: fix heap over-read in ibmasm_send_i2o_message()

The ibmasm_send_i2o_message() function uses get_dot_command_size() to compute the byte count for memcpy_toio(), but this value is derived from user-controlled fields in the dot_command_header (command_size: u8, data_size: u16) and is never validated against the actual allocation size. A root user can write a small buffer with inflated header fields, causing memcpy_toio() to read up to ~65 KB past the end of the allocation into adjacent kernel heap, which is then forwarded to the service processor over MMIO.

Silently clamping the copy size is not sufficient: if the header fields claim a larger size than the buffer, the SP receives a dot command whose own header is inconsistent with the I2O message length, which can cause the SP to desynchronize. Reject such commands outright by returning failure.

Validate command_size before calling get_mfa_inbound() to avoid leaking an I2O message frame: reading INBOUND_QUEUE_PORT dequeues a hardware frame from the controller's free pool, and returning without a corresponding set_mfa_inbound() call would permanently exhaust it.

Additionally, clamp command_size to I2O_COMMAND_SIZE before the memcpy_toio() so the MMIO write stays within the I2O message frame, consistent with the clamping already performed by outgoing_message_size() for the header field.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

A heap over-read in the Linux kernel's ibmasm driver lets a root user read ~65 KB of kernel heap via crafted dot command headers.

Vulnerability

The ibmasm_send_i2o_message() function in the Linux kernel's ibmasm driver uses get_dot_command_size() to compute the byte count for memcpy_toio(). This size is derived from user-controlled fields in the dot_command_header (command_size: u8, data_size: u16) and is never validated against the actual allocation size. A root user can write a small buffer with inflated header fields, causing memcpy_toio() to read up to ~65 KB past the end of the allocation into adjacent kernel heap. The vulnerability affects kernel versions prior to the fix commit fd19eb1c7504.

Exploitation

An attacker requires root privileges on the system. The attacker writes a small buffer to the driver, setting the command_size and data_size fields in the dot_command_header to values larger than the buffer. The driver then calls get_dot_command_size() which returns a large byte count, and memcpy_toio() reads beyond the buffer boundary into kernel heap memory. The read data is forwarded to the service processor over MMIO. Additionally, if the invalid command is not rejected, reading INBOUND_QUEUE_PORT dequeues a hardware frame without a corresponding set_mfa_inbound() call, which would permanently exhaust the frame pool.

Impact

Successful exploitation allows a root attacker to read up to ~65 KB of kernel heap memory, potentially leaking sensitive information such as cryptographic keys, process credentials, or other kernel data. The data is transmitted to the service processor, which may further expose it. The vulnerability could also lead to denial of service if the hardware frame pool is exhausted due to missing set_mfa_inbound() calls.

Mitigation

The fix is included in Linux kernel commit fd19eb1c75047a4ed4e855f56cafd704dc3914e0 [1]. The patch validates command_size before calling get_mfa_inbound() and rejects commands with inconsistent header fields by returning failure. Additionally, command_size is clamped to I2O_COMMAND_SIZE before the memcpy_toio() to ensure the MMIO write stays within the I2O message frame. No workaround is available; users should apply the kernel update. The vulnerability is not listed on CISA's Known Exploited Vulnerabilities (KEV) catalog as of publication.

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

1

Patches

10
c1c2417c60db

ibmasm: fix heap over-read in ibmasm_send_i2o_message()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitTyllis XuMar 14, 2026Fixed in 6.18.27via kernel-cna
2 files changed · +16 10
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
9e8f6c9d4ecd

ibmasm: fix heap over-read in ibmasm_send_i2o_message()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitTyllis XuMar 14, 2026Fixed in 7.0.4via kernel-cna
2 files changed · +16 10
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
fd19eb1c7504

ibmasm: fix heap over-read in ibmasm_send_i2o_message()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitTyllis XuMar 14, 2026Fixed in 6.6.140via kernel-cna
2 files changed · +16 10
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
fe31722b0194

ibmasm: fix heap over-read in ibmasm_send_i2o_message()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitTyllis XuMar 14, 2026Fixed in 6.12.86via kernel-cna
2 files changed · +16 10
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
9aad71144fa3

ibmasm: fix heap over-read in ibmasm_send_i2o_message()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitTyllis XuMar 14, 2026Fixed in 7.1-rc1via kernel-cna
2 files changed · +16 10
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
9e8f6c9d4ecd

ibmasm: fix heap over-read in ibmasm_send_i2o_message()

2 files changed · +16 10
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
c1c2417c60db

ibmasm: fix heap over-read in ibmasm_send_i2o_message()

2 files changed · +16 10
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
fd19eb1c7504

ibmasm: fix heap over-read in ibmasm_send_i2o_message()

2 files changed · +16 10
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
fe31722b0194

ibmasm: fix heap over-read in ibmasm_send_i2o_message()

2 files changed · +16 10
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
9aad71144fa3

ibmasm: fix heap over-read in ibmasm_send_i2o_message()

2 files changed · +16 10
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/misc/ibmasm/lowlevel.c+8 5 modified
    diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
    index 6922dc6c10db08..5313230f36ad4d 100644
    --- a/drivers/misc/ibmasm/lowlevel.c
    +++ b/drivers/misc/ibmasm/lowlevel.c
    @@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
     int ibmasm_send_i2o_message(struct service_processor *sp)
     {
     	u32 mfa;
    -	unsigned int command_size;
    +	size_t command_size;
     	struct i2o_message *message;
     	struct command *command = sp->current_command;
     
    +	command_size = get_dot_command_size(command->buffer);
    +	if (command_size > command->buffer_size)
    +		return 1;
    +	if (command_size > I2O_COMMAND_SIZE)
    +		command_size = I2O_COMMAND_SIZE;
    +
     	mfa = get_mfa_inbound(sp->base_address);
     	if (!mfa)
     		return 1;
     
    -	command_size = get_dot_command_size(command->buffer);
    -	header.message_size = outgoing_message_size(command_size);
    -
    +	header.message_size = outgoing_message_size((unsigned int)command_size);
     	message = get_i2o_message(sp->base_address, mfa);
     
     	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing validation of user-controlled dot_command header size fields against the actual buffer allocation allows a heap over-read in memcpy_toio()."

Attack vector

A root user writes a small command buffer to the kernel heap via the ibmasm device interface, but inflates the `command_size` and `data_size` fields in the `dot_command_header` to values far exceeding the real allocation. The `get_dot_command_size()` function derives a total size from these fields, and the original code passed this unchecked size to `memcpy_toio()`, causing it to read up to ~65 KB past the end of the heap allocation. The over-read data is forwarded over MMIO to the service processor, leaking adjacent kernel heap contents.

Affected code

The vulnerable function is `ibmasm_send_i2o_message()` in `drivers/misc/ibmasm/lowlevel.c` [patch_id=2660013]. The function calls `get_dot_command_size()` to compute the byte count for `memcpy_toio()`, using user-controlled fields (`command_size: u8`, `data_size: u16`) from the `dot_command_header` without validating them against the actual buffer allocation size.

What the fix does

The patch adds two checks before calling `get_mfa_inbound()`. First, it compares the computed `command_size` against `command->buffer_size` and returns failure if the header claims a larger size than the actual buffer, preventing the heap over-read. Second, it clamps `command_size` to `I2O_COMMAND_SIZE` so the subsequent `memcpy_toio()` stays within the I2O message frame. The validation is placed before `get_mfa_inbound()` to avoid leaking a hardware I2O message frame by dequeueing it and then returning without a corresponding `set_mfa_inbound()` call [patch_id=2660013].

Preconditions

  • authAttacker must have root privileges on the system to access the ibmasm device interface
  • inputAttacker must be able to write a dot_command buffer with crafted header fields (command_size, data_size) to the kernel heap

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.