diff options
author | Alexander Potapenko <glider@google.com> | 2018-09-06 08:21:54 +0000 |
---|---|---|
committer | Alexander Potapenko <glider@google.com> | 2018-09-06 08:21:54 +0000 |
commit | d518c5fc87f8dc8617671702af3bbdcea426c808 (patch) | |
tree | d91012078e7169f479d9e9cc76451cf749f511b7 /llvm/lib/Transforms | |
parent | 0a875b2f15b1285d36d1d9ce92404f75bd10e99a (diff) | |
download | bcm5719-llvm-d518c5fc87f8dc8617671702af3bbdcea426c808.tar.gz bcm5719-llvm-d518c5fc87f8dc8617671702af3bbdcea426c808.zip |
[MSan] Make sure variadic function arguments do not overflow __msan_va_arg_tls
Turns out that calling a variadic function with too many (e.g. >100 i64's)
arguments overflows __msan_va_arg_tls, which leads to smashing other TLS
data with function argument shadow values.
getShadow() already checks for kParamTLSSize and returns clean shadow if
the argument does not fit, so just skip storing argument shadow for such
arguments.
llvm-svn: 341525
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp | 73 |
1 files changed, 50 insertions, 23 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index 194d77c00ab..b3c31f5d53b 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -3318,9 +3318,11 @@ struct VarArgAMD64Helper : public VarArgHelper { assert(A->getType()->isPointerTy()); Type *RealTy = A->getType()->getPointerElementType(); uint64_t ArgSize = DL.getTypeAllocSize(RealTy); - Value *ShadowBase = - getShadowPtrForVAArgument(RealTy, IRB, OverflowOffset); + Value *ShadowBase = getShadowPtrForVAArgument( + RealTy, IRB, OverflowOffset, alignTo(ArgSize, 8)); OverflowOffset += alignTo(ArgSize, 8); + if (!ShadowBase) + continue; Value *ShadowPtr, *OriginPtr; std::tie(ShadowPtr, OriginPtr) = MSV.getShadowOriginPtr(A, IRB, IRB.getInt8Ty(), kShadowTLSAlignment, @@ -3337,11 +3339,13 @@ struct VarArgAMD64Helper : public VarArgHelper { Value *ShadowBase; switch (AK) { case AK_GeneralPurpose: - ShadowBase = getShadowPtrForVAArgument(A->getType(), IRB, GpOffset); + ShadowBase = + getShadowPtrForVAArgument(A->getType(), IRB, GpOffset, 8); GpOffset += 8; break; case AK_FloatingPoint: - ShadowBase = getShadowPtrForVAArgument(A->getType(), IRB, FpOffset); + ShadowBase = + getShadowPtrForVAArgument(A->getType(), IRB, FpOffset, 16); FpOffset += 16; break; case AK_Memory: @@ -3349,13 +3353,15 @@ struct VarArgAMD64Helper : public VarArgHelper { continue; uint64_t ArgSize = DL.getTypeAllocSize(A->getType()); ShadowBase = - getShadowPtrForVAArgument(A->getType(), IRB, OverflowOffset); + getShadowPtrForVAArgument(A->getType(), IRB, OverflowOffset, 8); OverflowOffset += alignTo(ArgSize, 8); } // Take fixed arguments into account for GpOffset and FpOffset, // but don't actually store shadows for them. if (IsFixed) continue; + if (!ShadowBase) + continue; IRB.CreateAlignedStore(MSV.getShadow(A), ShadowBase, kShadowTLSAlignment); } @@ -3367,7 +3373,10 @@ struct VarArgAMD64Helper : public VarArgHelper { /// Compute the shadow address for a given va_arg. Value *getShadowPtrForVAArgument(Type *Ty, IRBuilder<> &IRB, - int ArgOffset) { + unsigned ArgOffset, unsigned ArgSize) { + // Make sure we don't overflow __msan_va_arg_tls. + if (ArgOffset + ArgSize > kParamTLSSize) + return nullptr; Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy); Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset)); return IRB.CreateIntToPtr(Base, PointerType::get(MSV.getShadowTy(Ty), 0), @@ -3483,9 +3492,11 @@ struct VarArgMIPS64Helper : public VarArgHelper { if (ArgSize < 8) VAArgOffset += (8 - ArgSize); } - Base = getShadowPtrForVAArgument(A->getType(), IRB, VAArgOffset); + Base = getShadowPtrForVAArgument(A->getType(), IRB, VAArgOffset, ArgSize); VAArgOffset += ArgSize; VAArgOffset = alignTo(VAArgOffset, 8); + if (!Base) + continue; IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment); } @@ -3497,7 +3508,10 @@ struct VarArgMIPS64Helper : public VarArgHelper { /// Compute the shadow address for a given va_arg. Value *getShadowPtrForVAArgument(Type *Ty, IRBuilder<> &IRB, - int ArgOffset) { + unsigned ArgOffset, unsigned ArgSize) { + // Make sure we don't overflow __msan_va_arg_tls. + if (ArgOffset + ArgSize > kParamTLSSize) + return nullptr; Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy); Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset)); return IRB.CreateIntToPtr(Base, PointerType::get(MSV.getShadowTy(Ty), 0), @@ -3628,11 +3642,11 @@ struct VarArgAArch64Helper : public VarArgHelper { Value *Base; switch (AK) { case AK_GeneralPurpose: - Base = getShadowPtrForVAArgument(A->getType(), IRB, GrOffset); + Base = getShadowPtrForVAArgument(A->getType(), IRB, GrOffset, 8); GrOffset += 8; break; case AK_FloatingPoint: - Base = getShadowPtrForVAArgument(A->getType(), IRB, VrOffset); + Base = getShadowPtrForVAArgument(A->getType(), IRB, VrOffset, 8); VrOffset += 16; break; case AK_Memory: @@ -3641,7 +3655,8 @@ struct VarArgAArch64Helper : public VarArgHelper { if (IsFixed) continue; uint64_t ArgSize = DL.getTypeAllocSize(A->getType()); - Base = getShadowPtrForVAArgument(A->getType(), IRB, OverflowOffset); + Base = getShadowPtrForVAArgument(A->getType(), IRB, OverflowOffset, + alignTo(ArgSize, 8)); OverflowOffset += alignTo(ArgSize, 8); break; } @@ -3649,6 +3664,8 @@ struct VarArgAArch64Helper : public VarArgHelper { // bother to actually store a shadow. if (IsFixed) continue; + if (!Base) + continue; IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment); } Constant *OverflowSize = @@ -3658,7 +3675,10 @@ struct VarArgAArch64Helper : public VarArgHelper { /// Compute the shadow address for a given va_arg. Value *getShadowPtrForVAArgument(Type *Ty, IRBuilder<> &IRB, - int ArgOffset) { + unsigned ArgOffset, unsigned ArgSize) { + // Make sure we don't overflow __msan_va_arg_tls. + if (ArgOffset + ArgSize > kParamTLSSize) + return nullptr; Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy); Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset)); return IRB.CreateIntToPtr(Base, PointerType::get(MSV.getShadowTy(Ty), 0), @@ -3863,14 +3883,17 @@ struct VarArgPowerPC64Helper : public VarArgHelper { ArgAlign = 8; VAArgOffset = alignTo(VAArgOffset, ArgAlign); if (!IsFixed) { - Value *Base = getShadowPtrForVAArgument(RealTy, IRB, - VAArgOffset - VAArgBase); - Value *AShadowPtr, *AOriginPtr; - std::tie(AShadowPtr, AOriginPtr) = MSV.getShadowOriginPtr( - A, IRB, IRB.getInt8Ty(), kShadowTLSAlignment, /*isStore*/ false); - - IRB.CreateMemCpy(Base, kShadowTLSAlignment, AShadowPtr, - kShadowTLSAlignment, ArgSize); + Value *Base = getShadowPtrForVAArgument( + RealTy, IRB, VAArgOffset - VAArgBase, ArgSize); + if (Base) { + Value *AShadowPtr, *AOriginPtr; + std::tie(AShadowPtr, AOriginPtr) = + MSV.getShadowOriginPtr(A, IRB, IRB.getInt8Ty(), + kShadowTLSAlignment, /*isStore*/ false); + + IRB.CreateMemCpy(Base, kShadowTLSAlignment, AShadowPtr, + kShadowTLSAlignment, ArgSize); + } } VAArgOffset += alignTo(ArgSize, 8); } else { @@ -3898,8 +3921,9 @@ struct VarArgPowerPC64Helper : public VarArgHelper { } if (!IsFixed) { Base = getShadowPtrForVAArgument(A->getType(), IRB, - VAArgOffset - VAArgBase); - IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment); + VAArgOffset - VAArgBase, ArgSize); + if (Base) + IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment); } VAArgOffset += ArgSize; VAArgOffset = alignTo(VAArgOffset, 8); @@ -3917,7 +3941,10 @@ struct VarArgPowerPC64Helper : public VarArgHelper { /// Compute the shadow address for a given va_arg. Value *getShadowPtrForVAArgument(Type *Ty, IRBuilder<> &IRB, - int ArgOffset) { + unsigned ArgOffset, unsigned ArgSize) { + // Make sure we don't overflow __msan_va_arg_tls. + if (ArgOffset + ArgSize > kParamTLSSize) + return nullptr; Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy); Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset)); return IRB.CreateIntToPtr(Base, PointerType::get(MSV.getShadowTy(Ty), 0), |