Skip to content

Use After Free: Tracking alias #18791

Open
@ArtiomKr

Description

As I already asked, I want to understand, how can I track alias to detect use after free vulnerability? Are there any libraries, which can help track such CWEs? Here some examples:

#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;
}
#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;
}

I want to track malloc function and then find all alias (start tracking them). After that I want to make all arguments of free become sources and make them about alias. How is it can be shown?
For now I have code, that find only CWEs that are related only to the function argument:

/**
 * @name Use after free
 * @kind path-problem
 * @id cpp/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 |
       arg.asDefiningArgument() = call.getArgument(0) and
       call.getTarget().hasGlobalOrStdName("free")
     )
   }
 
   predicate isSink(DataFlow::Node sink) {
    exists(PointerDereferenceExpr star |
     star.getOperand() = sink.asExpr()
    )
    or
    exists(FormattingFunctionCall call |
     call.getArgument(0) = sink.asExpr()
    )
   }
 }
 
 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"

Maybe is it possible to track this nit by arg.asDefiningArgument() = call.getArgument(0), but as relation to the memory? So, that I could somehow track memory, not argument?

Can isAdditionalFlowStep help?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions