Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to track clone value #18760

Closed
ArtiomKr opened this issue Feb 12, 2025 · 2 comments
Closed

Is it possible to track clone value #18760

ArtiomKr opened this issue Feb 12, 2025 · 2 comments
Labels
question Further information is requested

Comments

@ArtiomKr
Copy link

Is it possible to search for UAF by tracking clones of arguments from the "free" function? For example, in this code:

/**
 * @name Use after free
 * @kind path-problem
 * @id cpp/workshop/use-after-free
 */
import cpp
import semmle.code.cpp.dataflow.DataFlow
import semmle.code.cpp.dataflow.TaintTracking
import Configs::PathGraph

module Config implements DataFlow::ConfigSig {
  predicate isSource(DataFlow::Node arg) {
    exists(FunctionCall call |
      call.getTarget().hasGlobalOrStdName("free") and
      arg.asDefiningArgument() = call.getArgument(0)
    )
  }

  predicate isSink(DataFlow::Node sink) {
    exists(Expr e |
      sink.asExpr() = e and
      dereferenced(e)
    )
  }

}

module Configs = TaintTracking::Global<Config>;

from Configs::PathNode source, Configs::PathNode sink
where Configs::hasFlowPath(source, sink)
select sink, source, sink,
  "Memory is freed here and used here, causing a potential vulnerability.",
  source, "freed here", sink, "used here"

Test 1:

#include <stdlib.h>
#include <time.h>

int main() {
  char *a = (char *)malloc(sizeof(char)); // Memory allocation
  char *b = a;
  if (a != NULL) {
    free(a); // Free allocated memory
  }
  *b = 'b'; // Use after free
  return 0;
}

Test 2:

#include <stdlib.h>
#include <time.h>

struct char2 {
  char *a;
  char *b;
};

int main() {
  struct char2 *c2_alias;
  struct char2 *c2 = (struct char2 *)malloc(sizeof(struct char2));
  c2->a = (char *)malloc(sizeof(char)); // Memory allocation
  c2_alias = c2;
  time_t seconds = time(NULL) % 3;
  free(c2->a); // Free memory which was allocated in 'c2->a'
  if (seconds >= 0 && seconds <= 2)
    *(c2_alias->a) = 'a'; // Use after free
  if (seconds >= 3)
    *(c2_alias->b) = 'b';
  free(c2);
  return 0;
}

Or is it necessary to somehow start from where the "malloc" was made?

@ArtiomKr ArtiomKr added the question Further information is requested label Feb 12, 2025
@jketema
Copy link
Contributor

jketema commented Feb 13, 2025

Hi @ArtiomKr,

You will indeed need to start tracking from the call to malloc. Note that this becomes non-trivial very fast, as you will need to figure out somehow whether the access to the alias occurs after the free. Even without looking at aliases it's hard to do this without generating many false positives. See here for our solution, which does not handle aliases.

@jketema
Copy link
Contributor

jketema commented Feb 17, 2025

Closing as answered, and for the remainer as a duplicate of #18791

@jketema jketema closed this as completed Feb 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants