From aec42e28763e784e5d839fee078b33900daf58b8 Mon Sep 17 00:00:00 2001 From: zhangzhenghsy Date: Mon, 4 Sep 2023 23:18:44 -0700 Subject: [PATCH] fix some small issues --- helper_functions/get_prioritylist.py | 6 ++- helper_functions/get_prioritylists.py | 35 +++++++++----- helper_functions/get_refkernel_results.py | 26 +++++++--- helper_functions/get_syzkaller.py | 50 +++++++++++++------ helper_functions/get_targetkernel_configs.py | 30 ++++++++++-- helper_functions/helper.py | 51 ++++++++++++++++++-- helper_functions/match_targetlines.py | 7 +-- helper_functions/prioritylist.py | 6 +-- lib/Core/Executor.cpp | 14 +----- lib/Core/SpecialFunctionHandler.cpp | 2 + lib/Kernel/Listener/UCListener.cpp | 31 ++++++++++-- lib/Kernel/Listener/UCListener.h | 2 +- 12 files changed, 193 insertions(+), 67 deletions(-) diff --git a/helper_functions/get_prioritylist.py b/helper_functions/get_prioritylist.py index 3df6e0d..bae63b1 100644 --- a/helper_functions/get_prioritylist.py +++ b/helper_functions/get_prioritylist.py @@ -110,7 +110,6 @@ def get_cover_lineinfo(PATH): print("\nget_cover_lineinfo()\n") prioritylist.get_cover_lineinfo(PATH) prioritylist.get_complete_coverage_coverline(PATH) - #if not os.path.exists(PATH + "/targetline"): if not os.path.exists(PATH+"/lineguidance/"): os.mkdir(PATH+"/lineguidance/") helper.get_callstack(PATH) @@ -190,10 +189,13 @@ def generate_kleeconfig(PATH): generate_kleeconfig(PATH) if option == "all": if not os.path.exists(PATH+"/vm.log_correct"): - run_SyzMorph_add(syzbothash) + #run_SyzMorph_add(syzbothash) compile_refkernel(PATH, syzbothash) else: print("skip run_SyzMorph_add/compile_refkernel since vm.log_correct exists") + if not os.path.exists(PATH+"/vm.log_correct"): + print("Please generate the vm.log_correct manually") + exit() get_cover_from_vmlog(PATH, syzbothash) get_cover_lineinfo(PATH) compile_bcfiles(PATH) diff --git a/helper_functions/get_prioritylists.py b/helper_functions/get_prioritylists.py index 0cb25d6..eff2f45 100644 --- a/helper_functions/get_prioritylists.py +++ b/helper_functions/get_prioritylists.py @@ -1,7 +1,8 @@ import helper import os, subprocess +import sys import json - +import get_syzkaller def get_prioritylist(PATH): print("get_prioritylist()") string1 = "cd /home/zzhan173/Linux_kernel_UC_KLEE;python3 helper_functions/get_prioritylist.py all "+PATH+">"+PATH+"/get_prioritylist_log 2>&1" @@ -21,33 +22,41 @@ def clean_files(PATH): print(string1) helper.command(string1) -OOBW_skipcases = ["6087eafb76a94c4ac9eb", "b055b1a6b2b958707a21", "a42d84593d6a89a76f26", "838eb0878ffd51f27c41", "cfc0247ac173f597aaaa"] +OOBW_skipcases = ["6087eafb76a94c4ac9eb", "b055b1a6b2b958707a21", "a42d84593d6a89a76f26", "838eb0878ffd51f27c41", "59af7bf76d795311da8c","cfc0247ac173f597aaaa", "dc3b1cf9111ab5fe98e7", "59b7daa4315e07a994f1"] OOBR_skipcases = ["35101610ff3e83119b1b", "37ba33391ad5f3935bbd","983cb8fb2d17a7af549d","a22c6092d003d6fe1122", "d29e9263e13ce0b9f4fd", "7d027845265d531ba506", "f68108fed972453a0ad4"] UAFR_skipcases = ["6720d64f31c081c2f708","cbb289816e728f56a4e2c1b854a3163402fe2f88", "9f43bb6a66ff96a21931", "5be8aebb1b7dfa90ef31"] UAFW_skipcases = ["c7d9ec7a1a7272dd71b3"] +#Reproducers don't trigger the vulnerability +UAF_skipcases = ["373ce58a5e9ddec1b8ee55d9f7353db5b565cdc3", "ad1f53726c3bd11180cb", "b75c138e9286ac742647" , "7be8b464a3a27e6dc5c73d3ffe3b56dc0cf51e52" , "13bef047dbfffa5cd1af"] +total_skipcases = OOBW_skipcases + OOBR_skipcases + UAFR_skipcases + UAFW_skipcases + UAF_skipcases if __name__ == "__main__": #with open("/home/zzhan173/Linux_kernel_UC_KLEE/cases/OOBRcases", "r") as f: # s_buf = f.readlines() #Type = "UAFR" - Type = "OOBR" + #Type = "OOBW" + Type = "UAF" PATH = "/data4/zzhan173/Fixtag_locator/"+Type+"_cases_filter.json" + specific_case = None + if len(sys.argv) > 1: + specific_case = sys.argv[1] with open(PATH, "r") as f: syzbothash_info = json.load(f) for syzbothash in syzbothash_info: - if syzbothash in OOBW_skipcases: - continue - if syzbothash in OOBR_skipcases: + if specific_case and syzbothash!=specific_case: continue - if syzbothash in UAFR_skipcases: - continue - if syzbothash in UAFW_skipcases: + if syzbothash in total_skipcases: continue PATH = "/data3/zzhan173/"+Type+"/"+syzbothash+"/refkernel" if not os.path.exists(PATH): os.makedirs(PATH) - if os.path.exists(PATH+"/configs/config_cover_doms.json"): + i386 = None + if "386" in syzbothash_info[syzbothash]["manager"]: + i386 = True + + if not specific_case and os.path.exists(PATH+"/configs/config_cover_doms.json"): print("\nAlready generated config_cover_doms.json, skip", PATH,"\n") continue - else: - print("\nHave not generated config_cover_doms.json", PATH) - get_prioritylist(PATH) + syzkaller_commit = syzbothash_info[syzbothash]["syzkaller"] + print("\nHave not generated config_cover_doms.json", PATH) + get_syzkaller.compile_syzkaller(PATH, syzkaller_commit, i386) + get_prioritylist(PATH) diff --git a/helper_functions/get_refkernel_results.py b/helper_functions/get_refkernel_results.py index 52f8bbe..926d5c0 100644 --- a/helper_functions/get_refkernel_results.py +++ b/helper_functions/get_refkernel_results.py @@ -2,6 +2,7 @@ import helper from multiprocessing import Pool import json +import get_prioritylists def run_klee(arguments): config, output = arguments @@ -30,7 +31,7 @@ def generate_configlist(PATH): calltrace = config_cover_doms["97_calltrace"] new_config_cover_doms = config_cover_doms - length = 3 + length = 1 while length < len(calltrace): new_calltrace = calltrace[-1*length:] new_config_cover_doms["97_calltrace"] = new_calltrace @@ -50,11 +51,24 @@ def get_configlist(PATH): if __name__ == "__main__": config_output = [] - with open("/home/zzhan173/Linux_kernel_UC_KLEE/cases/OOBRcases", "r") as f: - s_buf = f.readlines() - for syzbothash in s_buf: - syzbothash = syzbothash[:-1] - PATH = "/data3/zzhan173/OOBR/"+syzbothash+"/refkernel" + #with open("/home/zzhan173/Linux_kernel_UC_KLEE/cases/OOBRcases", "r") as f: + # s_buf = f.readlines() + #for syzbothash in s_buf: + Type = "UAF" + PATH = "/data4/zzhan173/Fixtag_locator/"+Type+"_cases_filter.json" + + specific_hash = None + if len(sys.argv) > 1: + specific_hash = sys.argv[1] + total_skipcases = get_prioritylists.total_skipcases + with open(PATH, "r") as f: + syzbothash_info = json.load(f) + for syzbothash in syzbothash_info: + if syzbothash in total_skipcases: + continue + if specific_hash and syzbothash != specific_hash: + continue + PATH = "/data3/zzhan173/" + Type + "/"+syzbothash+"/refkernel" generate_configlist(PATH) configlist = get_configlist(PATH) for config in configlist: diff --git a/helper_functions/get_syzkaller.py b/helper_functions/get_syzkaller.py index 9c14022..ed07dec 100644 --- a/helper_functions/get_syzkaller.py +++ b/helper_functions/get_syzkaller.py @@ -6,43 +6,58 @@ def command(string1): result=p.stdout.readlines() return result -def get_go12_syzkaller(commit): +def get_go12_syzkaller(commit, i386=None): os.environ['GOPATH'] = "/home/zzhan173/syzkaller/GO12/gopath" os.environ['GOROOT'] = "/home/zzhan173/syzkaller/GO12/goroot" os.environ['PATH'] = os.environ['GOROOT'] + "/bin:" + os.environ['GOPATH'] + "/bin:" + os.environ['PATH'] string1 = "cd /home/zzhan173/syzkaller/GO12/gopath/src/github.com/google/syzkaller; git checkout -f "+commit+";" #print(string1) command(string1) - string1 = "cd /home/zzhan173/syzkaller/GO12/gopath/src/github.com/google/syzkaller; make;" + string1 = "cd /home/zzhan173/syzkaller/GO12/gopath/src/github.com/google/syzkaller; make" + if i386: + string1 += " TARGETVMARCH=amd64 TARGETARCH=386" command(string1) -def copy_go12_syzkaller(targetdir): +def copy_go12_syzkaller(targetdir, i386=None): string1 = "cp /home/zzhan173/syzkaller/GO12/gopath/src/github.com/google/syzkaller/bin/linux_amd64/* "+targetdir command(string1) + if i386: + string1 = "cp /home/zzhan173/syzkaller/GO12/gopath/src/github.com/google/syzkaller/bin/linux_386/* "+targetdir + command(string1) -def get_go14_syzkaller(commit): +def get_go14_syzkaller(commit, i386=None): os.environ['GOPATH'] = "/home/zzhan173/syzkaller/GO14/gopath" os.environ['GOROOT'] = "/home/zzhan173/syzkaller/GO14/goroot" os.environ['PATH'] = os.environ['GOROOT'] + "/bin:" + os.environ['GOPATH'] + "/bin:" + os.environ['PATH'] string1 = "cd /home/zzhan173/syzkaller/GO14/gopath/src/github.com/google/syzkaller; git checkout -f "+commit+";make" + if i386: + string1 += " TARGETVMARCH=amd64 TARGETARCH=386" command(string1) -def copy_go14_syzkaller(targetdir): +def copy_go14_syzkaller(targetdir, i386=None): string1 = "cp /home/zzhan173/syzkaller/GO14/gopath/src/github.com/google/syzkaller/bin/linux_amd64/* "+targetdir command(string1) + if i386: + string1 = "cp /home/zzhan173/syzkaller/GO14/gopath/src/github.com/google/syzkaller/bin/linux_386/* "+targetdir + command(string1) -def get_go16_syzkaller(commit): +def get_go16_syzkaller(commit, i386=None): os.environ['GOPATH'] = "/home/zzhan173/syzkaller/GO16/gopath" os.environ['GOROOT'] = "/home/zzhan173/syzkaller/GO16/go" os.environ['PATH'] = os.environ['GOROOT'] + "/bin:" + os.environ['GOPATH'] + "/bin:" + os.environ['PATH'] #print("os.environ['PATH']:", os.environ['PATH']) string1 = "cd /home/zzhan173/syzkaller/GO16; cd syzkaller; git checkout -f "+commit+";make" + if i386: + string1 += " TARGETVMARCH=amd64 TARGETARCH=386" print(string1) command(string1) -def copy_go16_syzkaller(targetdir): +def copy_go16_syzkaller(targetdir, i386=None): string1 = "cp /home/zzhan173/syzkaller/GO16/syzkaller/bin/linux_amd64/* "+targetdir command(string1) + if i386: + string1 = "cp /home/zzhan173/syzkaller/GO16/syzkaller/bin/linux_386/* "+targetdir + command(string1) def get_goversion(commit): string1 = "cd /home/zzhan173/repos/syzkaller;git checkout -f "+commit @@ -62,7 +77,8 @@ def get_goversion(commit): print("dont find suitable go version from setup.md for", commit) return None -def compile_syzkaller(targetdir, commit): +def compile_syzkaller(targetdir, commit, i386=None): + print("compile_syzkaller()", targetdir, commit, i386) targetdir += "/syzkaller/" print("compile_syzkaller() ",commit, "for", targetdir) if not os.path.exists(targetdir): @@ -70,14 +86,14 @@ def compile_syzkaller(targetdir, commit): goversion = get_goversion(commit) print("goversion:", goversion) if goversion == "go12": - get_go12_syzkaller(commit) - copy_go12_syzkaller(targetdir) + get_go12_syzkaller(commit, i386) + copy_go12_syzkaller(targetdir, i386) elif goversion == "go14": - get_go14_syzkaller(commit) - copy_go14_syzkaller(targetdir) + get_go14_syzkaller(commit, i386) + copy_go14_syzkaller(targetdir, i386) elif goversion == "go16": - get_go16_syzkaller(commit) - copy_go16_syzkaller(targetdir) + get_go16_syzkaller(commit, i386) + copy_go16_syzkaller(targetdir, i386) else: "compile_syzkaller Fail" return False @@ -90,4 +106,8 @@ def compile_syzkaller(targetdir, commit): #commit = "da505f84d3e8fc3bb7c54fea76eb5574987ee01a" targetdir = sys.argv[1] commit = sys.argv[2] - compile_syzkaller(targetdir, commit) + i386 = None + if len(sys.argv) > 3: + i386 = True + print("i386") + compile_syzkaller(targetdir, commit, i386) diff --git a/helper_functions/get_targetkernel_configs.py b/helper_functions/get_targetkernel_configs.py index f1b2134..c145d1f 100644 --- a/helper_functions/get_targetkernel_configs.py +++ b/helper_functions/get_targetkernel_configs.py @@ -5,6 +5,7 @@ import shutil import get_refkernel_results from multiprocessing import Pool +import get_prioritylists repo_PATH = { "linux":"/home/zzhan173/repos/linux/" @@ -101,6 +102,8 @@ def get_targetkernel_configs(Type, specific_hashvalue = None): if specific_hashvalue: if hashvalue != specific_hashvalue: continue + if hashvalue in get_prioritylists.total_skipcases: + print("skip", hashvalue) for targetkernel in hash_targetkernels[hashvalue]: intputlist += [(Type, hashvalue, targetkernel)] print("length of inputlist:", len(intputlist)) @@ -120,6 +123,21 @@ def run_klees(Type, specific_hashvalue = None): config = PATH2+"/configs/config_cover_doms.json" output = PATH2+"/configs/output" + with open(config, "r") as f: + klee_config = json.load(f) + target_line_list = klee_config["4_target_line_list"] + target_line_list = [line for line in target_line_list if line != "manualget"] + if len(target_line_list) == 0: + with open(output, "w") as f: + f.write("target line not exist") + print(hashvalue, targetkernel, "target line not exist") + continue + + + #if os.path.exists(output): + # print("already generate the output, continue") + # continue + PATH1 = "/data3/zzhan173/"+Type+"/"+hashvalue+"/refkernel" helper.generate_kleeconfig_newentry(PATH1, PATH2) if os.path.exists(config): @@ -134,10 +152,14 @@ def run_klees(Type, specific_hashvalue = None): #repo = "/home/zzhan173/repos/linux" #tag = "v5.4" #get_targetkernel(PATH, repo, tag) - Type = "OOBR" + specifichash = None + if len(sys.argv) > 1: + specifichash = sys.argv[1] + #Type = "OOBR" + #Type = "OOBW" + Type = "UAF" - get_targetkernel_configs(Type, sys.argv[1]) - #run_klees(Type) - run_klees(Type, sys.argv[1]) + get_targetkernel_configs(Type, specifichash) + run_klees(Type, specifichash) diff --git a/helper_functions/helper.py b/helper_functions/helper.py index f202220..339b7e9 100644 --- a/helper_functions/helper.py +++ b/helper_functions/helper.py @@ -117,6 +117,12 @@ def get_callstack(PATH): for refkernel in refkernels: for i in range(len(s_buf)): s_buf[i] = s_buf[i].replace(refkernel, "") + + for i in range(len(s_buf)): + line = s_buf[i] + if "Allocated by" in line: + s_buf = s_buf[:i] + break for i in range(len(s_buf)): line = s_buf[i] @@ -127,7 +133,7 @@ def get_callstack(PATH): return False s_buf = s_buf[i+1:] - entry_funcs = ["do_sys", "_sys_", "syscall"] + entry_funcs = ["do_sys", "_sys_", "syscall", "asm_exc_page_fault"] for i in range(len(s_buf)): if any(func in s_buf[i] for func in entry_funcs): break @@ -136,7 +142,7 @@ def get_callstack(PATH): return False s_buf = s_buf[:i] - Ignore_funcs = ["kasan", "memcpy"] + Ignore_funcs = ["kasan", "memcpy", "memset"] startline = 0 for i in range(len(s_buf)): if any(func in s_buf[i] for func in Ignore_funcs): @@ -176,7 +182,7 @@ def get_allocate_callstack(PATH): return False s_buf = s_buf[:i] - Ignore_funcs = ["kasan", "memcpy"] + Ignore_funcs = ["kasan", "memcpy", "memset"] startline = 0 for i in range(len(s_buf)): if any(func in s_buf[i] for func in Ignore_funcs): @@ -581,6 +587,9 @@ def generate_kleeconfig_newentry(PATH1, PATH2): string1 = "cd "+ PATH2 + "/configs; cp config_cover_doms.json config_cover_doms_old.json" command(string1) + OOBdetected_entry = generate_OOBdetected_entry(PATH1) + print("OOBdetected_entry:", OOBdetected_entry) + with open(configpath, "r") as f: config = json.load(f) oldcalltrace = config['97_calltrace'] @@ -589,11 +598,17 @@ def generate_kleeconfig_newentry(PATH1, PATH2): if len(oldcalltrace) > 5: config['97_calltrace'] = oldcalltrace[-5:] config['3_entry_function'] = oldcalltrace[-5] + if OOBdetected_entry and OOBdetected_entry in config['97_calltrace']: + config['97_calltrace'] = oldcalltrace[oldcalltrace.index(OOBdetected_entry):] + config['3_entry_function'] = OOBdetected_entry elif new_entryfunc not in oldcalltrace: print("new_entryfunc not in oldcalltrace", new_entryfunc, PATH2) if len(oldcalltrace) > 5: config['97_calltrace'] = oldcalltrace[-5:] config['3_entry_function'] = oldcalltrace[-5] + if OOBdetected_entry and OOBdetected_entry in config['97_calltrace']: + config['97_calltrace'] = oldcalltrace[oldcalltrace.index(OOBdetected_entry):] + config['3_entry_function'] = OOBdetected_entry else: print("new_entryfunc in oldcalltrace", PATH2) config['97_calltrace'] = oldcalltrace[oldcalltrace.index(new_entryfunc):] @@ -601,6 +616,36 @@ def generate_kleeconfig_newentry(PATH1, PATH2): with open(configpath, "w") as f: json.dump(config, f, indent=4) +def generate_OOBdetected_entry(PATH): + configs_dir = PATH + "/configs" + files = os.listdir(configs_dir) + + config_files = [configs_dir + "/" + filename for filename in files if filename.endswith('.json')] + + calltrace_len = 0 + entry = None + for config in config_files: + calltrace = get_config_calltrace(config) + output = config.replace(".json", "_output") + if not os.path.exists(output): + continue + OOBdetected = check_output_OOBdetected(output) + if OOBdetected: + if len(calltrace) > calltrace_len: + entry = calltrace[0] + calltrace_len = len(calltrace) + return entry + +def get_config_calltrace(config): + with open(config, "r") as f: + config = json.load(f) + return config["97_calltrace"] +def check_output_OOBdetected(output): + with open(output, "r") as f: + s_buf = f.readlines() + s_buf = s_buf[-1000:] + return any("OOB detected in target line" in line for line in s_buf) + if __name__ == "__main__": #caller = "netlink_sendmsg" #callee = "netlink_unicast" diff --git a/helper_functions/match_targetlines.py b/helper_functions/match_targetlines.py index b61b066..2780564 100644 --- a/helper_functions/match_targetlines.py +++ b/helper_functions/match_targetlines.py @@ -81,7 +81,7 @@ def get_diff_buf(refkernel, targetkernel, PATH2): #compilebc.format_linux(target_kernel) if os.path.exists(PATH2 +"/diffbuf"): os.remove(PATH2 +"/diffbuf") - string1 = "git diff --no-index "+refkernel+" "+targetkernel+" >" + PATH2 +"/diffbuf" + string1 = "git diff --no-index --patience "+refkernel+" "+targetkernel+" >" + PATH2 +"/diffbuf" print(string1) result = command(string1) @@ -159,7 +159,7 @@ def get_matchedlines(PATH1, PATH2): return filter_line_targetline def get_matchedlines_git(PATH1, PATH2): - string1 = "git diff --no-index "+PATH1+" "+PATH2 + string1 = "git diff --no-index --patience "+PATH1+" "+PATH2 print(string1) p_buf = command(string1) p_buf = [line.decode("utf-8") for line in p_buf] @@ -491,4 +491,5 @@ def generate_kleeconfig_targetkernel(PATH2): if __name__ == "__main__": PATH2 = sys.argv[1] - helper.get_mustBBs(PATH2) \ No newline at end of file + helper.get_mustBBs(PATH2) + generate_kleeconfig_targetkernel(PATH2) diff --git a/helper_functions/prioritylist.py b/helper_functions/prioritylist.py index ce214ea..ad0eb18 100644 --- a/helper_functions/prioritylist.py +++ b/helper_functions/prioritylist.py @@ -1040,8 +1040,9 @@ def generate_kleeconfig(PATH, parameterlist = []): with open(PATH+"/4_target_line_list", "r") as f: s_buf = f.readlines() else: - with open(PATH+"/targetline", "r") as f: + with open(PATH+"/cleancallstack_format", "r") as f: s_buf = f.readlines() + s_buf = [s_buf[0].split(" ")[1]] for line in s_buf: target_line_list += [line[:-1]] target_line_list = [helper.simplify_path(line) for line in target_line_list] @@ -1736,8 +1737,6 @@ def get_BBlinelist_doms(PATH): #requirement: vm.log, config_withoutkasan, calltracefunclist def get_all(PATH): - if not os.path.exists(PATH + "/targetline"): - helper.get_targetline_format(PATH) with open(PATH+"/targetline", "r") as f: targetline = f.readlines()[0][:-1] print("targetline:", targetline) @@ -1755,6 +1754,7 @@ def get_all(PATH): get_BBlist(PATH) get_BBlinelist_doms(PATH) cfg_analysis.get_cfg_files(PATH) + helper.get_targetline_format(PATH) generate_kleeconfig(PATH, []) def get_cover_from_vmlog(PATH): diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index e79d9a3..5125fe7 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -3991,7 +3991,7 @@ void Executor::run(ExecutionState &initialState) { //auto execute_time = std::time(NULL)-start_time; auto execute_time = ((double)(clock() - start_time))/CLOCKS_PER_SEC; - if (execute_time > 12000) { + if (execute_time > 7200) { // todo: check if target line has been reached? klee::klee_message("execution time out (12000) we think there is no OOB triggerred"); haltExecution = true; @@ -4666,18 +4666,6 @@ void Executor::executeMemoryOperation(ExecutionState &state, check = optimizer.optimizeExpr(check, true); //std::cout << "check:" << (check.ptr)->dump2() <<"\n"; - /// zheng: check whether it's symbolic size - //std::cout << "mo->issymsize: " << mo->issymsize << "\n"; - /*if (!mo->issymsize.compare("True")){ - ref symsize = mo->symsize; - //klee::klee_message("mo->issymsize True symsize: %s", symsize.get_ptr()->dump2().c_str()); - //std::cout << "mo->issymsize True symsize of object:\n"; - //std::cout << (symsize.ptr)->dump2() << "\n"; - check = UltExpr::create(offset, symsize); - klee::klee_message("mo->issymsize True new check: %s", check.get_ptr()->dump2().c_str()); - //std::cout << "new check:\n" << (check.ptr)->dump2() <<"\n"; - }*/ - bool inBounds; solver->setTimeout(coreSolverTimeout); bool success = solver->mustBeTrue(state.constraints, check, inBounds, diff --git a/lib/Core/SpecialFunctionHandler.cpp b/lib/Core/SpecialFunctionHandler.cpp index 98feaa1..41569a6 100644 --- a/lib/Core/SpecialFunctionHandler.cpp +++ b/lib/Core/SpecialFunctionHandler.cpp @@ -1248,6 +1248,8 @@ void SpecialFunctionHandler::handleStrcmp(ExecutionState &state, if (ConstantExpr* CE2 = dyn_cast(targetaddr)) { success2 = state.addressSpace.resolveOne(CE2, op2); } else { + ref ret = ConstantExpr::alloc(0, target->inst->getType()->getIntegerBitWidth()); + executor.bindLocal(target, state, ret); return; } diff --git a/lib/Kernel/Listener/UCListener.cpp b/lib/Kernel/Listener/UCListener.cpp index 7c051f5..fded9bb 100644 --- a/lib/Kernel/Listener/UCListener.cpp +++ b/lib/Kernel/Listener/UCListener.cpp @@ -392,6 +392,11 @@ void kuc::UCListener::beforeExecuteInstruction(klee::ExecutionState &state, klee //Note that we will match all the corresponding symaddrs (within the size) to the object klee::ref concrete_addr = create_symaddr_object(state, ki, base, ty, 64); executor->un_eval(ki, 1, state).value = concrete_addr; + + //base = executor->eval(ki, 2, state).value; + //ty = ki->inst->getOperand(2)->getType(); + //concrete_addr = create_symaddr_object(state, ki, base, ty, 64); + //executor->un_eval(ki, 2, state).value = concrete_addr; } if (name == "memcpy" || name == "_copy_from_user" || name == "_copy_to_user" || name == "strncpy_from_user") { klee::ref base = executor->eval(ki, 1, state).value; @@ -1238,6 +1243,11 @@ void kuc::UCListener::OOBWcheck(klee::ExecutionState &state, klee::KInstruction break; } case llvm::Instruction::GetElementPtr: { + // If the object is allocated outside SE scope, (pointed by a symbolic pointer). + // We simply check if the len(index) is symbolic and can be larger than a large constant + ref baseaddr = executor->eval(ki, 0, state).value; + ref index = executor->eval(ki, 1, state).value; + OOB_check2(state, baseaddr, index, 16); break; /* klee::ObjectPair op; @@ -1315,8 +1325,8 @@ void kuc::UCListener::OOBWcheck(klee::ExecutionState &state, klee::KInstruction } // If the object is allocated outside SE scope, (pointed by a symbolic pointer). // We simply check if the len is symbolic and can be larger than a large constant - OOB_check2(state, srcaddr, len); - OOB_check2(state, targetaddr, len); + OOB_check2(state, srcaddr, len, 512); + OOB_check2(state, targetaddr, len, 512); targetaddr = AddExpr::create(targetaddr, len); srcaddr = AddExpr::create(srcaddr, len); targetaddr = SubExpr::create(targetaddr, klee::ConstantExpr::create(1, Context::get().getPointerWidth())); @@ -1324,6 +1334,15 @@ void kuc::UCListener::OOBWcheck(klee::ExecutionState &state, klee::KInstruction OOB_check(state, targetaddr, 1); OOB_check(state, srcaddr, 1); } + if (name == "memset"){ + ref targetaddr = executor->eval(ki, 1, state).value; + ref len = executor->eval(ki, 3, state).value; + OOB_check2(state, targetaddr, len, 512); + targetaddr = AddExpr::create(targetaddr, len); + targetaddr = SubExpr::create(targetaddr, klee::ConstantExpr::create(1, Context::get().getPointerWidth())); + OOB_check(state, targetaddr, 1); + + } } } } @@ -1364,13 +1383,17 @@ void kuc::UCListener::extract_baseaddr(ref &symaddr, ref &baseaddr) } } -void kuc::UCListener::OOB_check2(klee::ExecutionState &state, ref targetaddr, ref len) { +void kuc::UCListener::OOB_check2(klee::ExecutionState &state, ref targetaddr, ref len, uint64_t thresholdlen) { + if (klee::ConstantExpr* CE1 = dyn_cast(len)) { + klee_message("OOB_check2() len is concrete"); + return; + } ref baseaddress = klee::ConstantExpr::create(0, klee::Context::get().getPointerWidth());; extract_baseaddr(targetaddr, baseaddress); klee::ConstantExpr *CE = dyn_cast(baseaddress); if(CE->getZExtValue() == 0){ klee_message("OOB_check2() object allocated outside the SE scope"); - ref threshold_size = klee::ConstantExpr::create(512, klee::Context::get().getPointerWidth()); + ref threshold_size = klee::ConstantExpr::create(thresholdlen, len->getWidth()); ref check = UleExpr::create(len, threshold_size); klee::klee_message("check: %s", check.get_ptr()->dump2().c_str()); bool inBounds; diff --git a/lib/Kernel/Listener/UCListener.h b/lib/Kernel/Listener/UCListener.h index b311bf9..46dbe73 100644 --- a/lib/Kernel/Listener/UCListener.h +++ b/lib/Kernel/Listener/UCListener.h @@ -31,7 +31,7 @@ namespace kuc { void OOBWcheck(klee::ExecutionState &state, klee::KInstruction *ki); void OOB_check(klee::ExecutionState &state, klee::ref targetaddr, unsigned bytes); - void OOB_check2(klee::ExecutionState &state, klee::ref targetaddr, klee::ref len); + void OOB_check2(klee::ExecutionState &state, klee::ref targetaddr, klee::ref len, u_int64_t thresholdlen); void separateConstantAndSymbolic(const klee::ref &expr, std::set> &constants, std::set> &symbolics); void extract_baseaddr(klee::ref &symaddr, klee::ref &baseaddr); klee::ref create_symaddr_object(klee::ExecutionState &state, klee::KInstruction *ki, klee::ref base, llvm::Type *ty, unsigned size);