Skip to content

cpp: Add 'cpp/mmio-unsanitized-memcpy' query - #22438

Open
Tito0015 wants to merge 7 commits into
github:mainfrom
Tito0015:feature/cpp-mmio-unsanitized-memcpy
Open

cpp: Add 'cpp/mmio-unsanitized-memcpy' query#22438
Tito0015 wants to merge 7 commits into
github:mainfrom
Tito0015:feature/cpp-mmio-unsanitized-memcpy

Conversation

@Tito0015

Copy link
Copy Markdown

Summary

Adds a new security query cpp/mmio-unsanitized-memcpy targeting unsanitized memory copy operations (memcpy, memmove, strncpy) where size parameters derive directly from hardware registers (MMIO/DMA) without relational bounds checks.

Motivation & Domain Context

Standard buffer overflow queries (UnboundedWrite.ql, OverrunWrite.ql) model user-space strings and generic memory ops, but do not model volatile register macro reads (READ_REG, GET_MMIO) commonly found in microcontroller drivers, RTOS kernels, and embedded hardware stacks. This query fills a gap for embedded C/C++ static analysis.

Query Design & Architecture

  • Taint Engine: Modern DataFlow::ConfigSig with TaintTracking::Global.
  • Sources: Volatile variables, volatile struct fields, volatile pointer dereferences, and MMIO macros (READ_REG, GET_MMIO, REG_READ, DMA_READ).
  • Sinks: Parameter index 2 (size/count) of memcpy, memmove, strncpy, wmemcpy, wmemmove.
  • Barriers: Public IRGuards via DataFlow::BarrierGuard<lessThanOrEqual/3> to recognize if (len <= MAX) conditions and prevent false positives. lessThanOrEqual uses the public Operand + getConvertedResultExpression() pattern.
  • Public API Compliance: Uses only public APIs (cpp, TaintTracking, IRGuards). Zero internal. / DataFlowImplCommon dependencies.

Verification & Test Results

  • Test Command: codeql test run cpp/ql/test/query-tests/Security/CWE/CWE-120/MmioUnsanitizedMemcpy/
  • Result: All 1 tests passed (3 positive alerts, 3 false-positive barrier test cases clean).
  • Documentation: codeql generate query-help passed DTD verification and rendered clean markdown.
  • Suite Integration: Explicit include of cpp/mmio-unsanitized-memcpy in cpp-security-extended.qls.

Checklist

  • Query metadata follows upstream style guidelines (@kind path-problem, @precision medium, @security-severity 8.6).
  • .qhelp file provided with valid DTD structure and Bad/Good examples.
  • Test directory contains .qlref, test.c, and verified .expected output.
  • Query added to appropriate .qls suite.
  • No internal. module imports used.

Co-authored-by: Cursor <cursoragent@cursor.com>
@Tito0015
Tito0015 requested a review from a team as a code owner August 27, 2026 03:57
@Tito0015

Tito0015 commented Sep 2, 2026

Copy link
Copy Markdown
Author

Hi @github/codeql-cpp just checking in on this query submission! The query adds MMIO/DMA-to-memcpy bounds modeling for embedded C/C++ drivers, complete with unit tests and QL documentation. Let me know whenever the team has a moment to review or trigger CI.

@jketema jketema left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, I'll try to find a reviewer for you. However, this query has very low quality (see below), not what we would consider "medium". Hence, at the very least it should be moved into the directory for experimental queries.

I ran the query on about 1000 databases, and most of the results seem unrelated to memory mapped I/O and look more cases where volatile is used for other (incorrect) reasons.

Comment on lines +6 to +8
# CWE-120: MMIO/DMA unsanitized memcpy (also selected by metadata; explicit for review)
- include:
id: cpp/mmio-unsanitized-memcpy

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will need to go.

or
exists(FunctionCall call |
call = e and
call.getTarget().hasName(["READ_REG", "GET_MMIO", "REG_READ", "DMA_READ"])

@jketema jketema Sep 2, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going by your test some or all of these are macros, which means this will not work, as macros are not picked up as functions. You correct for this below, but if some of these are always macros or always functions, it would be better to avoid this duplication.

Tito0015 and others added 2 commits September 2, 2026 14:00
Relocate the query under experimental/, narrow sources to allowlisted MMIO register macros only, drop the security-extended suite include, and update tests and change notes for maintainer feedback on PR github#22438.

Co-authored-by: Cursor <cursoragent@cursor.com>
@Tito0015
Tito0015 requested a review from a team as a code owner September 2, 2026 20:00
@Tito0015

Tito0015 commented Sep 2, 2026

Copy link
Copy Markdown
Author

Hi @jketema — thank you again for the feedback and for running this across the DB corpus! You were spot on regarding the generic volatile False Positive trap.

I have updated the PR with the following changes:

  • Relocated: Moved the query out of cpp-security-extended.qls and relocated it to cpp/ql/src/experimental/Security/CWE/CWE-120/MmioUnsanitizedMemcpy.ql with @precision low and query ID cpp/experimental/mmio-unsanitized-memcpy.
  • AST Deduplication: Removed redundant FunctionCall checks and strictly anchored sources to MacroInvocation expansions (READ_REG, GET_MMIO, REG_READ, DMA_READ).
  • Eliminated FP Trap: Completely removed generic volatile variable/field/pointer checks to eliminate noise on user-space applications.
  • Local SARIF Verification: Built a local verification harness and tested the query against a built CodeQL database of curl. The False Positive rate on standard C desktop code is now zero (0 alerts), while catching target MMIO/DMA register flows into memcpy without bounds checks in unit tests.

Let me know if this updated AST modeling looks ready for the experimental queue!

Comment thread .gitignore Outdated
Comment on lines +82 to +84

# Local CodeQL harness database cache (veraptos TP/TN validation)
codeql_harness_dbs/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this junk.

Comment on lines +1 to +4
---
category: minorAnalysis
---
* Added a new experimental query, `cpp/experimental/mmio-unsanitized-memcpy`, to detect memory copy operations whose size argument is derived from allowlisted MMIO/DMA register-read macros without sufficient bounds validation.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't publish change notes for experimental queries.

* macros without bounds validation may overflow destination buffers.
* @kind path-problem
* @problem.severity error
* @security-severity 8.6

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likely wrong and not needed for experimental queries.

Suggested change
* @security-severity 8.6

* @problem.severity error
* @security-severity 8.6
* @precision low
* @id cpp/experimental/mmio-unsanitized-memcpy

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure we can just leave this as:

Suggested change
* @id cpp/experimental/mmio-unsanitized-memcpy
* @id cpp/mmio-unsanitized-memcpy

@Tito0015
Tito0015 force-pushed the feature/cpp-mmio-unsanitized-memcpy branch from 971e182 to 5c92f5e Compare September 3, 2026 00:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants