-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit c28ecf4
Showing
27,364 changed files
with
4,475,109 additions
and
0 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/fs.img | ||
/bin/llvm/ | ||
/private/ | ||
|
||
*~ | ||
*.as | ||
*# | ||
*.cmake | ||
*.def | ||
tags | ||
Release+Asserts | ||
|
||
# for testing | ||
test-as/Makefile | ||
|
||
# auto-generated | ||
*.llvm* | ||
*.config | ||
*.cfg | ||
*.log | ||
*.status | ||
*.spec | ||
*.bak | ||
|
||
|
||
llvm/include/llvm/Config/config.h | ||
llvm/include/llvm/Config/llvm-config.h | ||
llvm/include/llvm/Support/DataTypes.h | ||
|
||
# tmp directory | ||
tmp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
APISan: Sanitizing API Usages through Semantic Cross-Checking | ||
============================================================= | ||
|
||
Environments | ||
------------ | ||
- Tested in Ubuntu 14.04 | ||
- Setup | ||
```sh | ||
$ ./setup.sh | ||
``` | ||
- How to build symbolic database | ||
```sh | ||
$ apisan build [cmds] | ||
``` | ||
- Run './configure' | ||
```sh | ||
$ apisan build ./configure | ||
$ apisan build make | ||
``` | ||
- How to run a checker | ||
```sh | ||
$ apisan check --db=[db] --checker=[checker] | ||
``` | ||
- Example | ||
```sh | ||
$ cd test/return-value | ||
$ ../../apisan build make | ||
$ ../../apisan check --checker=rvchk | ||
``` | ||
|
||
Checkers (under analyzer/apisan/check) | ||
-------------------------------------- | ||
- Return value checker: retval.py | ||
- Argument checker: argument.py | ||
- Causality checker: causality.py | ||
- Condition checker: condition.py | ||
- Integer overflow checker: intovfl.py | ||
- Format string bug checker: fsb.py | ||
|
||
Authors | ||
------- | ||
- Insu Yun <insu@gatech.edu> | ||
- Changwoo Min <changwoo@gatech.edu> | ||
- Xujie Si <six@gatech.edu> | ||
- Yeongjin Jang <yeongjin.jang@gatech.edu> | ||
- Taesoo Kim <taesoo@gatech.edu> | ||
- Mayur Naik <naik@cc.gatech.edu> | ||
|
||
Publications | ||
------------ | ||
``` | ||
@inproceedings{yun:apisan, | ||
title = {{APISan: Sanitizing API Usages through Semantic Cross-checking}}, | ||
author = {Insu Yun and Changwoo Min and Xujie Si and Yeongjin Jang and Taesoo Kim and Mayur Naik}, | ||
booktitle = {Proceedings of the 25th USENIX Security Symposium (Security)}, | ||
month = aug, | ||
year = 2016, | ||
address = {Austin, TX}, | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
parser.out | ||
parsetab.py |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
from apisan.parse.explorer import Explorer | ||
from apisan.check.argument import ArgChecker | ||
from apisan.check.causality import CausalityChecker | ||
from apisan.check.condition import CondChecker | ||
from apisan.check.echo import EchoChecker | ||
from apisan.check.fsb import FSBChecker | ||
from apisan.check.intovfl import IntOvflChecker | ||
from apisan.check.retval import RetValChecker | ||
|
||
CHECKERS = { | ||
"rvchk": RetValChecker, | ||
"cpair": CausalityChecker, | ||
"cond": CondChecker, | ||
"fsb": FSBChecker, | ||
"args": ArgChecker, | ||
"intovfl": IntOvflChecker | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
#!/usr/bin/env python3 | ||
from .checker import Checker, Context, BugReport | ||
from ..parse.explorer import is_call | ||
from ..lib import config | ||
from ..parse.symbol import CallSymbol, IDSymbol | ||
|
||
def extract_nodes(arg): | ||
s = set() | ||
stack = [arg] | ||
while stack: | ||
arg = stack.pop() | ||
for child in arg.children: | ||
stack.append(child) | ||
if isinstance(arg, IDSymbol): | ||
s.add(arg) | ||
return s | ||
|
||
def check_related(arg1, arg2): | ||
if not (isinstance(arg1, CallSymbol) or | ||
isinstance(arg2, CallSymbol)): | ||
return False | ||
|
||
nodes1 = extract_nodes(arg1) | ||
nodes2 = extract_nodes(arg2) | ||
return bool(nodes1 & nodes2) | ||
|
||
class ArgContext(Context): | ||
def get_bugs(self): | ||
added = set() | ||
bugs = [] | ||
for key, value in self.ctx_uses.items(): | ||
total = self.total_uses[key] | ||
related = len(value[True]) | ||
score = related / len(total) | ||
codes = value[False] | ||
if score >= config.THRESHOLD and score != 1: | ||
for bug in codes: | ||
br = BugReport(score, bug, key, False) | ||
added.add(bug) | ||
bugs.append(br) | ||
return bugs | ||
|
||
class ArgChecker(Checker): | ||
def _initialize_process(self): | ||
self.context = ArgContext() | ||
|
||
def _process_path(self, path): | ||
for i, node in enumerate(path): | ||
if is_call(node): | ||
call = node.event.call | ||
code = node.event.code | ||
for i, arg1 in enumerate(call.args): | ||
for j in range(i + 1, len(call.args)): | ||
arg2 = call.args[j] | ||
related = check_related(arg1, arg2) | ||
self.context.add((call.name, i, j), related, code) | ||
|
||
def _finalize_process(self): | ||
return self.context | ||
|
||
def merge(self, ctxs): | ||
if not ctxs: | ||
return None | ||
ctx = ctxs[0] | ||
for i in range(1, len(ctxs)): | ||
ctx.merge(ctxs[i]) | ||
return self.rank(ctx.get_bugs()) | ||
|
||
def rank(self, reports): | ||
return sorted(reports, key=lambda k: k.score, reverse=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
#!/usr/bin/env python3 | ||
from .checker import Checker, Context | ||
from ..lib.rank_utils import ( | ||
is_alloc, is_dealloc, is_lock, is_unlock | ||
) | ||
from ..parse.explorer import is_call | ||
from ..parse.symbol import IDSymbol | ||
|
||
class CausalityContext(Context): | ||
def __init__(self): | ||
super().__init__() | ||
self.entries = {} | ||
|
||
def add_or_intersect(self, key, values, code): | ||
entry = (key, code) | ||
if entry in self.entries: | ||
self.entries[entry] &= values | ||
else: | ||
self.entries[entry] = values | ||
|
||
def add_all(self): | ||
for entry, values in self.entries.items(): | ||
key, code = entry | ||
for value in values: | ||
self.add(key, value, code) | ||
self.add(key, None, code) | ||
|
||
class CausalityChecker(Checker): | ||
def _initialize_process(self): | ||
self.context = CausalityContext() | ||
|
||
def _process_path(self, path): | ||
# get latest manager | ||
cmgr = path[-1].cmgr | ||
for i, node in enumerate(path): | ||
if is_call(node): | ||
call = node.event.call | ||
code = node.event.code | ||
constraint = cmgr.get(call) | ||
# want to use as dictionary key | ||
if constraint is not None: | ||
constraint = tuple(constraint) | ||
|
||
calls = set() | ||
for j in range(i + 1, len(path)): | ||
ff_node = path[j] | ||
if (is_call(ff_node) | ||
and ff_node.event.call.name != call.name): | ||
calls.add(ff_node.event.call.name) | ||
self.context.add_or_intersect((call.name, constraint), calls, code) | ||
|
||
def _finalize_process(self): | ||
self.context.add_all() | ||
return self.context | ||
|
||
def merge(self, ctxs): | ||
if not ctxs: | ||
return None | ||
ctx = ctxs[0] | ||
for i in range(1, len(ctxs)): | ||
ctx.merge(ctxs[i]) | ||
return self.rank(ctx.get_bugs()) | ||
|
||
def rank(self, reports): | ||
for report in reports: | ||
func = report.key[0] | ||
if not isinstance(func, IDSymbol): | ||
continue | ||
ctx = report.ctx | ||
if not isinstance(ctx, IDSymbol): | ||
continue | ||
|
||
func_name = func.id | ||
ctx_name = ctx.id | ||
|
||
if is_alloc(func_name) and is_dealloc(ctx_name): | ||
report.score += 0.5 | ||
elif is_lock(func_name) and is_unlock(ctx_name): | ||
report.score += 0.5 | ||
elif is_dealloc(ctx_name): | ||
report.score += 0.3 | ||
return sorted(reports, key=lambda k: k.score, reverse=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
#!/usr/bin/env python3 | ||
from ..parse.explorer import is_eop | ||
from ..lib import config | ||
from ..lib.store import Store | ||
|
||
class BugReport(): | ||
def __init__(self, score, code, key, ctx): | ||
self.key = key | ||
self.ctx = ctx | ||
self.score = score | ||
self.code = code | ||
|
||
def __repr__(self): | ||
return "BugReport(score=%.02f, code=%s, key=%s, ctx=%s" % ( | ||
self.score, self.code, self.key, self.ctx | ||
) | ||
|
||
class Context(): | ||
def __init__(self): | ||
self.total_uses = Store(level=1) | ||
self.ctx_uses = Store(level=2) | ||
|
||
def add(self, key, value, code): | ||
if value is not None: | ||
self.ctx_uses[key][value].add(code) | ||
self.total_uses[key].add(code) | ||
|
||
def merge(self, other): | ||
self.total_uses.merge(other.total_uses) | ||
self.ctx_uses.merge(other.ctx_uses) | ||
|
||
def get_bugs(self): | ||
added = set() | ||
bugs = [] | ||
for key, value in self.ctx_uses.items(): | ||
total = self.total_uses[key] | ||
for ctx, codes in value.items(): | ||
score = len(codes) / len(total) | ||
if score >= config.THRESHOLD and score != 1: | ||
diff = total - codes | ||
for bug in diff: | ||
br = BugReport(score, bug, key, ctx) | ||
added.add(bug) | ||
bugs.append(br) | ||
return bugs | ||
|
||
class Checker(object): | ||
def _initialize_process(self): | ||
# optional | ||
pass | ||
|
||
def _finalize_process(self): | ||
raise NotImplementedError | ||
|
||
def _process_path(self, path): | ||
raise NotImplementedError | ||
|
||
def process(self, tree): | ||
self._initialize_process() | ||
self._do_dfs(tree) | ||
return self._finalize_process() | ||
|
||
def _do_dfs(self, tree): | ||
count = 0 | ||
indices = [0] | ||
nodes = [tree.root] | ||
|
||
while nodes: | ||
index = indices.pop() | ||
node = nodes.pop() | ||
if is_eop(node): | ||
nodes.append(node) | ||
# delayed visiting for truncated paths | ||
self._process_path(nodes) | ||
nodes.pop() | ||
count += 1 | ||
else: | ||
if len(node.children) > index: | ||
indices.append(index + 1) | ||
nodes.append(node) | ||
|
||
child = node.children[index] | ||
child.visited = False | ||
indices.append(0) | ||
nodes.append(child) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#!/usr/bin/env python3 | ||
from .checker import Checker, Context | ||
from ..lib import utils, rank_utils | ||
from ..lib.rank_utils import ( | ||
is_alloc, is_dealloc, is_lock, is_unlock | ||
) | ||
from ..parse.explorer import is_call | ||
from ..parse.symbol import IDSymbol | ||
|
||
class CondChecker(Checker): | ||
def _initialize_process(self): | ||
self.context = Context() | ||
|
||
def _process_path(self, path): | ||
# get latest manager | ||
cmgr = path[-1].cmgr | ||
for i, node in enumerate(path): | ||
if is_call(node): | ||
call = node.event.call | ||
code = node.event.code | ||
cstr = cmgr.get(call, True) | ||
# want to use as dictionary key | ||
constraints = set() | ||
for j in range(0, len(path)): | ||
if i == j: # skip myself | ||
continue | ||
ff_node = path[j] | ||
if is_call(ff_node): | ||
ff_call = ff_node.event.call | ||
other_cstr = cmgr.get(ff_call, True) | ||
self.context.add((call.name, cstr), (ff_call.name, other_cstr), code) | ||
|
||
def _finalize_process(self): | ||
return self.context | ||
|
||
def merge(self, ctxs): | ||
if not ctxs: | ||
return None | ||
ctx = ctxs[0] | ||
for i in range(1, len(ctxs)): | ||
ctx.merge(ctxs[i]) | ||
return self.rank(ctx.get_bugs()) | ||
|
||
def rank(self, reports): | ||
return sorted(reports, key=lambda k:k.score, reverse=True) |
Oops, something went wrong.