[PATCH] [ASan] Initial support for Kernel AddressSanitizer

Alexander Potapenko glider at google.com
Mon Jun 15 06:49:58 PDT 2015


Addressed Alexey's comments.
Regarding the missing tests, I think it's best to add them at opt level, but I can't do that now because there's no command line switch that enables KASan (this mode only depends on the bool passed to the pass factory). I can add such a switch, but then it can be used to work around the "ASan xor KASan" restriction. WDYT?


================
Comment at: lib/Transforms/Instrumentation/AddressSanitizer.cpp:1359
@@ -1349,3 +1358,3 @@
 
   bool Changed = false;
 
----------------
ygribov wrote:
> samsonov wrote:
> > Wait a second.... Do you do *anything* in AddressSanitizerModule pass in `CompileKernel` mode? You don't add module constructor, and you don't instrument globals. Maybe, we should just avoid creating this pass in the first place?
> Or perhaps instrumentation of globals will follow shortly so it's ok to have this pass at hand.
> Or perhaps instrumentation of globals will follow shortly so it's ok to have this pass at hand.
Exactly, my intention was to add it soon.

================
Comment at: lib/Transforms/Instrumentation/AddressSanitizer.cpp:1379
@@ -1368,2 +1378,3 @@
       const std::string ExpStr = Exp ? "exp_" : "";
+      const std::string SuffixStr = CompileKernel ? "N" : "_n";
       const Type *ExpType = Exp ? Type::getInt32Ty(*C) : nullptr;
----------------
ygribov wrote:
> Perhaps use "_noabort" suffix to match gcc?
Looks like I've been comparing to the wrong gcc version, 4.9 didn't have the 'noabort' suffixes. Fixed.

================
Comment at: lib/Transforms/Instrumentation/AddressSanitizer.cpp:1405
@@ -1393,1 +1404,3 @@
+  const std::string MemIntrinCallbackPrefix =
+      CompileKernel ? std::string("") : ClMemoryAccessCallbackPrefix;
   AsanMemmove = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
----------------
samsonov wrote:
> Hm... So you don't have __asan_memset() in the kernel. Maybe, we shouldn't instrument mem intrinsics in this case at all, not replace intrinisics with call to plain memset()?
mm/kasan/kasan.c redefines memset() et al. making them call __asan_{load,store}N (see https://github.com/ramosian-glider/kasan/blob/kasan_llvmlinux/mm/kasan/kasan.c#L263), so we just replace the intrinsics with calls to memset().

================
Comment at: lib/Transforms/Instrumentation/AddressSanitizer.cpp:1441
@@ +1440,3 @@
+  if (!CompileKernel) {
+    std::tie(AsanCtorFunction, AsanInitFunction) =
+        createSanitizerCtorAndInitFunctions(M, kAsanModuleCtorName,
----------------
samsonov wrote:
> You will access uninitialized memory in `AddressSanitizer::runOnFunction` (potentially in `AddressSanitizer::maybeInsertAsanInitAtFunctionEntry` as well, but the latter is relevant only for Mac).
In fact I didn't fully understand this piece before. I've looked std::tie up and it's more clear to me now.
Moved the assignment outside the condition (or shall we NULL-initialize these fields instead?)

================
Comment at: lib/Transforms/Instrumentation/AddressSanitizer.cpp:1530
@@ -1515,3 +1529,3 @@
 
-  bool UseCalls = false;
+  bool UseCalls = CompileKernel;
   if (ClInstrumentationWithCallsThreshold >= 0 &&
----------------
samsonov wrote:
>   bool UseCalls = CompileKernel || (ClInstrumentationWithCallsThreshold >= 0 && ...);
Done.

================
Comment at: tools/clang/include/clang/Basic/Sanitizers.def:44
@@ -43,1 +43,3 @@
 
+// Kernel AddressSanitizer (KASAN)
+SANITIZER("kernel-address", KernelAddress)
----------------
samsonov wrote:
> What is the "correct" way to capitalize it? KASAN? KASan?
It hasn't been established yet, but Dima says we prefer "KASan" (which surprised me). Fixed here and in tools/clang/lib/CodeGen/CodeGenModule.cpp

================
Comment at: tools/clang/lib/AST/Decl.cpp:3684
@@ -3683,2 +3683,3 @@
   ASTContext &Context = getASTContext();
-  if (!Context.getLangOpts().Sanitize.has(SanitizerKind::Address) ||
+  if (!(Context.getLangOpts().Sanitize.has(SanitizerKind::Address) ||
+        Context.getLangOpts().Sanitize.has(SanitizerKind::KernelAddress)) ||
----------------
samsonov wrote:
> Wow, that's hard to parse. I'd vote for adding a method to `SanitizerSet`
>   if (!Context.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address, SanitizerKind::KernelAddress)
>     ...
> 
> That would also be useful in several places below.
I've added SanitizerSet::hasAsanOrKasan() -- did you mean that?

================
Comment at: tools/clang/lib/CodeGen/BackendUtil.cpp:211
@@ +210,3 @@
+  PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/true));
+  PM.add(createAddressSanitizerModulePass(/*CompileKernel*/true));
+}
----------------
samsonov wrote:
> See note above - I'm not sure we need a module pass for that.
Can we keep it provided that we'll have module-level instrumentation soon?

================
Comment at: tools/clang/lib/CodeGen/CodeGenFunction.cpp:619
@@ -619,2 +618,3 @@
+  if (SanOpts.has(SanitizerKind::Address) || SanOpts.has(SanitizerKind::KernelAddress))
     Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
   if (SanOpts.has(SanitizerKind::Thread))
----------------
Note I'm using the same attribute for both userspace and kernel instrumentation. I think we don't need to distinguish between them.

http://reviews.llvm.org/D10411

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/






More information about the llvm-commits mailing list