Skip to content

[BUG] Lack of Error Code Verification Causes Memory Info Leak #19417

Description

@catalinv-ncc

Description / Steps to reproduce the issue

Impact

An attacker able to force an unsuccessful RFID read operation can force the kernel to disclose kernel stack information. The called may be able to use the stack content information as part of a more complex attack that can allow privilege escalation.

Description

The contactless kernel driver relies on the read operation implemented by mfrc522_read():

static const struct file_operations g_mfrc522fops =
{
  mfrc522_open,   /* open */
  mfrc522_close,  /* close */
  [[[[mfrc522_read,   /* read */]]]]
...
};

The read operation uses mfrc522_picc_select() which has over 400 lines of code and 9 early return statements. An attacker able to inject bad data on the SPI bus between the NuttX-powered host and the MFRC522 IC may be able cause one of the tests in mfrc522_picc_select() to fail. If the call fails, the uninitialized kernel stack contents of uid (a 12-byte struct picc_uid_s) are returned to the user space caller.

static ssize_t [[[[mfrc522_read]]]](FAR struct file *filep, [[[[FAR char *buffer]]]], size_t buflen)
{
...
  [[[[FAR struct picc_uid_s uid;]]]]
...
  /* Now read the UID */
  [[[[mfrc522_picc_select(dev, &uid, 0);]]]]

  if ([[[[uid.sak != PICC_TYPE_NOT_COMPLETE]]]])
    {
      /* TODO: double/triple UID */

      if (buffer)
        {
          [[[[snprintf(buffer, buflen, "0x%02X%02X%02X%02X",
                   uid.uid_data[0], uid.uid_data[1],
                   uid.uid_data[2], uid.uid_data[3]);]]]]
          return buflen;
        }
    }

  return OK;
}

Since the mfrc522_picc_select() may fail silently, uid is left uninitialized, specifically uid.sak. As such, the verification uid.sak != PICC_TYPE_NOT_COMPLETE is likely to be true and the content of the kernel stack is leaked to the user space caller.

[[[[int]]]] mfrc522_picc_select(FAR struct mfrc522_dev_s *dev, FAR struct picc_uid_s *uid, uint8_t validbits)
{
...
      else
        {
          uid_complete = true;
          [[[[uid->sak = resp_buf[0];]]]]
        }
    }

  /* Set correct uid->size */
  uid->size = 3 * cascade_level + 1;
  return OK;
}

Recommendation

  • Before snprintf() reads uid, it must be initialized: FAR struct picc_uid_s uid = 0;
  • Function mfrc522_read() must check the mfrc522_picc_select() return code, and propagate the error.

On which OS does this issue occur?

[OS: Linux]

What is the version of your OS?

Ubuntu 24.04

NuttX Version

master

Issue Architecture

[Arch: all]

Issue Area

[Area: Drivers]

Host information

No response

Verification

  • I have verified before submitting the report.

Metadata

Metadata

Assignees

Labels

Arch: allIssues that apply to all architecturesArea: DriversDrivers issuesOS: LinuxIssues related to Linux (building system, etc)Type: BugSomething isn't working

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions