Skip to content

Commit

Permalink
Add extra class for handling taint-sensitive functions
Browse files Browse the repository at this point in the history
Source- and sink-functions are now handled by a seperate class. This
allows us to re-use those functions among different types of
Taint-Analysis, e.g. IDE or Mono.

Functionality to import user-specified source- and sink-functions in
JSON format is also implemented. We also provide already specified
source- and sink-functions covering most common functions, e.g. fread,
fwrite etc. To ease the process of testing corner cases of a
Taint-Analysis, a pair of dummy source- and sink-functions can be used.
  • Loading branch information
rleer committed Aug 28, 2018
1 parent 7a2faf6 commit 95db64d
Show file tree
Hide file tree
Showing 13 changed files with 424 additions and 111 deletions.
20 changes: 20 additions & 0 deletions config/phasar-source-sink-function.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"Source Functions": {
"source()": {
"Args": [],
"Return": true
},
"read": {
"Args": [0, 1, 3],
"Return": false
}
},
"Sink Functions": {
"sink(int)": {
"Args": [0]
},
"write": {
"Args": [1]
}
}
}
2 changes: 1 addition & 1 deletion docs/Doxyfile.in
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ PROJECT_NAME = "Phasar"
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = 0.8
PROJECT_NUMBER = 1.1

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down
2 changes: 2 additions & 0 deletions include/phasar/Config/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ extern const std::string CompileCommandsJson;
extern boost::program_options::variables_map VariablesMap;
/// Log file directory
extern const std::string LogFileDirectory;
/// Default Source- and Sink-Functions path
extern const std::string DefaultSourceSinkFunctionsPath;
// Variables to be used in JSON export format
/// Identifier for call graph export
extern const std::string JsonCallGraphID;
Expand Down
68 changes: 17 additions & 51 deletions include/phasar/PhasarLLVM/IfdsIde/Problems/IFDSTaintAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <vector>

#include <phasar/PhasarLLVM/IfdsIde/DefaultIFDSTabulationProblem.h>
#include <phasar/PhasarLLVM/Utils/TaintSensitiveFunctions.h>

// Forward declaration of types for which we only use its pointer or ref type
namespace llvm {
Expand All @@ -30,75 +31,40 @@ namespace psr {

class LLVMBasedICFG;

// clang-format off
/**
* This analysis tracks data-flows through a program. Data flows from
* dedicated source functions, which generate tainted values, into
* dedicated sink functions. A leak is reported once a tainted value
* reached a sink function.
*
* Functions that are considered as taint-sensitve functions:
*
* Source functions| critical argument(s) | signature
* -----------------------------------------------------
* fgetc | ret | int fgetc(FILE *stream);
* fgets |0,ret| char *fgets(char *s, int size, FILE *stream);
* fread | 0 | size_t fread(void *ptr, size_t size,
* size_t nmemb, FILE *stream);
* getc | ret | int getc(FILE *stream);
* getchar | ret | int getchar(void);
* read | 1 | size_t read(int fd, void *buf, size_t count);
* ungetc | ret | int ungetc(int c, FILE *stream);
*
* Sink functions| critical argument(s) | signature
* -----------------------------------------------------
* fputc | 0 | int fputc(int c, FILE *stream);
* fputs | 0 | int fputs(const char *s, FILE *stream);
* fwrite | 0 | size_t fwrite(const void *ptr, size_t size,
* size_t nmemb, FILE *stream);
* printf | all | int printf(const char *format, ...);
* putc | 0 | int putc(int c, FILE *stream);
* putchar | 0 | int putchar(int c);
* puts | 0 | int puts(const char *s);
* write | 1 | size_t write(int fd, const void *buf, size_t count);
*/ // clang-format on
* @see TaintSensitiveFunctions on how to specify your own
* taint-sensitive source and sink functions.
*/
class IFDSTaintAnalysis : public DefaultIFDSTabulationProblem<
const llvm::Instruction *, const llvm::Value *,
const llvm::Function *, LLVMBasedICFG &> {
private:
std::vector<std::string> EntryPoints;

public:
typedef const llvm::Value *d_t;
typedef const llvm::Instruction *n_t;
typedef const llvm::Function *m_t;
typedef LLVMBasedICFG &i_t;

struct SourceFunction {
std::string name;
std::vector<unsigned> genargs;
bool genreturn;
SourceFunction(std::string n, std::vector<unsigned> gen, bool genret)
: name(n), genargs(gen), genreturn(genret) {}
SourceFunction(std::string n, bool genret) : name(n), genreturn(genret) {}
friend std::ostream &operator<<(std::ostream &os, const SourceFunction &sf);
};

struct SinkFunction {
std::string name;
std::vector<unsigned> sinkargs;
SinkFunction(std::string n, std::vector<unsigned> sink)
: name(n), sinkargs(sink) {}
friend std::ostream &operator<<(std::ostream &os, const SinkFunction &sf);
};
private:
TaintSensitiveFunctions SourceSinkFunctions;
std::vector<std::string> EntryPoints;

public:
/// Holds all leaks found during the analysis
std::map<n_t, std::set<d_t>> Leaks;

static const std::map<std::string, SourceFunction> Sources;

static const std::map<std::string, SinkFunction> Sinks;

IFDSTaintAnalysis(i_t icfg, std::vector<std::string> EntryPoints = {"main"});
/**
*
* @param icfg
* @param TSF
* @param EntryPoints
*/
IFDSTaintAnalysis(i_t icfg, TaintSensitiveFunctions TSF,
std::vector<std::string> EntryPoints = {"main"});

virtual ~IFDSTaintAnalysis() = default;

Expand Down
145 changes: 145 additions & 0 deletions include/phasar/PhasarLLVM/Utils/TaintSensitiveFunctions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/******************************************************************************
* Copyright (c) 2017 Philipp Schubert.
* All rights reserved. This program and the accompanying materials are made
* available under the terms of LICENSE.txt.
*
* Contributors:
* Philipp Schubert and others
*****************************************************************************/

/*
* TaintSensitiveFunctions.h
*
* Created on: 25.08.2018
* Author: richard leer
*/

#ifndef PHASAR_PHASARLLVM_UTILS_TAINTSENSITIVEFUNCTIONS_H
#define PHASAR_PHASARLLVM_UTILS_TAINTSENSITIVEFUNCTIONS_H

#include <iosfwd>
#include <map>
#include <string>
#include <vector>

#include <phasar/Config/Configuration.h>

namespace psr {
// clang-format off
/**
* The following functions are considered to as taint-sensitve functions by default:
*
* Source functions| Critical argument(s) | Signature
* ----------------|----------------------|-----------
* fgetc | ret | int fgetc(FILE *stream)
* fgets | 0, ret | char *fgets(char *s, int size, FILE *stream)
* fread | 0 | size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
* getc | ret | int getc(FILE *stream)
* getchar | ret | int getchar(void)
* read | 1 | size_t read(int fd, void *buf, size_t count)
* ungetc | ret | int ungetc(int c, FILE *stream)
*
* <br>
* Sink functions| Critical argument(s) | Signature
* --------------|----------------------|-----------
* fputc | 0 | int fputc(int c, FILE *stream)
* fputs | 0 | int fputs(const char *s, FILE *stream)
* fwrite | 0 | size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
* printf | all | int printf(const char *format, ...)
* putc | 0 | int putc(int c, FILE *stream)
* putchar | 0 | int putchar(int c)
* puts | 0 | int puts(const char *s)
* write | 1 | size_t write(int fd, const void *buf, size_t count)
*
* User specified source and sink functions can be imported as JSON.
*
* @brief Holds all taint-relevant source and sink functions.
*/ // clang-format on
class TaintSensitiveFunctions {
public:
/**
* Encapsulates all taint-relevant information of a source function.
*/
struct SourceFunction {
/// Function name.
std::string Name;
/// States which function parameter are tainted.
std::vector<unsigned> TaintedArgs;
/// States if the function return is tainted.
bool TaintsReturn;

SourceFunction(std::string FunctionName, std::vector<unsigned> Args,
bool Ret)
: Name(std::move(FunctionName)), TaintedArgs(std::move(Args)),
TaintsReturn(Ret){};
SourceFunction(std::string FunctionName, bool Ret)
: Name(std::move(FunctionName)), TaintsReturn(Ret){};
bool isTaintedArg(unsigned ArgIdx);
friend std::ostream &operator<<(std::ostream &OS, const SourceFunction &SF);
friend bool operator==(const SourceFunction &Lhs,
const SourceFunction &Rhs);
};

/**
* Encapsulates all taint-relevant information of a sink function.
*/
struct SinkFunction {
/// Funciton name.
std::string Name;
/// States which function arguments will be leaked.
std::vector<unsigned> LeakedArgs;

SinkFunction(std::string FunctionName, std::vector<unsigned> Args)
: Name(std::move(FunctionName)), LeakedArgs(std::move(Args)){};
bool isLeakedArg(unsigned ArgIdx);
friend std::ostream &operator<<(std::ostream &OS, const SinkFunction &SF);
friend bool operator==(const SinkFunction &Lhs, const SinkFunction &Rhs);
};

private:
// Object id's for parsing JSON
std::string SourceJSONId = "Source Functions";
std::string SinkJSONId = "Sink Functions";
std::string ArgumentJSONId = "Args";
std::string ReturnJSONId = "Return";

public:
/// Holds all source functions
std::map<std::string, SourceFunction> Sources;
/// Holds all source functions
std::map<std::string, SinkFunction> Sinks;

/**
* The dummy function have the following signature:
* - int source()
* - void sink(int)
*
* @brief Initializes default source and sink functions, or uses dummy source
* and sink functions.
*/
TaintSensitiveFunctions(bool useDummySourceSink = false);
~TaintSensitiveFunctions() = default;

bool isSource(const std::string &FunctionName) const;
bool isSink(const std::string &FunctionName) const;
SourceFunction getSource(const std::string &FunctionName);
SinkFunction getSink(const std::string &FunctionName);
friend std::ostream &operator<<(std::ostream &OS,
const TaintSensitiveFunctions &TSF);

/**
* Source and sink functions have to be in JSON format. An template file can
* be found in the config/ directory. Note that C++ source/sink function
* name's have to be demangled.
*
* @brief Allows to import user specified source and sink functions.
* @param FilePath path to JSON file holdind source and sink function
* definitions.
*/
void importSourceSinkFunctions(
const std::string &FilePath = DefaultSourceSinkFunctionsPath);
};

} // namespace psr

#endif
3 changes: 2 additions & 1 deletion lib/Config/Configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
namespace bpo = boost::program_options;
namespace bfs = boost::filesystem;

using namespace std;
using namespace psr;

namespace psr {
Expand All @@ -48,6 +47,8 @@ const std::string HeaderSearchPathsFileName("standard_header_paths.conf");
const std::string CompileCommandsJson("compile_commands.json");
bpo::variables_map VariablesMap;
const std::string LogFileDirectory("log/");
const std::string DefaultSourceSinkFunctionsPath(
PhasarDirectory + "config/phasar-source-sink-function.json");
const std::string JsonCallGraphID("CallGraph");
const std::string JsonTypeHierarchyID("TypeHierarchy");
const std::string JsonPointToGraphID("PointsToGraph");
Expand Down
3 changes: 2 additions & 1 deletion lib/Controller/AnalysisController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ AnalysisController::AnalysisController(
START_TIMER("DFA Runtime");
switch (analysis) {
case DataFlowAnalysisType::IFDS_TaintAnalysis: {
IFDSTaintAnalysis TaintAnalysisProblem(ICFG, EntryPoints);
TaintSensitiveFunctions TSF;
IFDSTaintAnalysis TaintAnalysisProblem(ICFG, TSF, EntryPoints);
LLVMIFDSSolver<const llvm::Value *, LLVMBasedICFG &> LLVMTaintSolver(
TaintAnalysisProblem, true);
LLVMTaintSolver.solve();
Expand Down
Loading

0 comments on commit 95db64d

Please sign in to comment.