@@ -593,6 +593,11 @@ struct DFSanFunction {
593
593
// / CTP(other types, PS) = PS
594
594
Value *collapseToPrimitiveShadow (Value *Shadow, Instruction *Pos);
595
595
596
+ void storeZeroPrimitiveShadow (Value *Addr, uint64_t Size , Align ShadowAlign,
597
+ Instruction *Pos);
598
+
599
+ Align getShadowAlign (Align InstAlignment);
600
+
596
601
private:
597
602
// / Collapses the shadow with aggregate type into a single primitive shadow
598
603
// / value.
@@ -634,6 +639,8 @@ class DFSanVisitor : public InstVisitor<DFSanVisitor> {
634
639
void visitGetElementPtrInst (GetElementPtrInst &GEPI);
635
640
void visitLoadInst (LoadInst &LI);
636
641
void visitStoreInst (StoreInst &SI);
642
+ void visitAtomicRMWInst (AtomicRMWInst &I);
643
+ void visitAtomicCmpXchgInst (AtomicCmpXchgInst &I);
637
644
void visitReturnInst (ReturnInst &RI);
638
645
void visitCallBase (CallBase &CB);
639
646
void visitPHINode (PHINode &PN);
@@ -648,6 +655,8 @@ class DFSanVisitor : public InstVisitor<DFSanVisitor> {
648
655
void visitMemTransferInst (MemTransferInst &I);
649
656
650
657
private:
658
+ void visitCASOrRMW (Align InstAlignment, Instruction &I);
659
+
651
660
// Returns false when this is an invoke of a custom function.
652
661
bool visitWrappedCallBase (Function &F, CallBase &CB);
653
662
@@ -1802,6 +1811,11 @@ void DFSanVisitor::visitInstOperandOrigins(Instruction &I) {
1802
1811
DFSF.setOrigin (&I, CombinedOrigin);
1803
1812
}
1804
1813
1814
+ Align DFSanFunction::getShadowAlign (Align InstAlignment) {
1815
+ const Align Alignment = ClPreserveAlignment ? InstAlignment : Align (1 );
1816
+ return Align (Alignment.value () * DFS.ShadowWidthBytes );
1817
+ }
1818
+
1805
1819
Value *DFSanFunction::loadFast16ShadowFast (Value *ShadowAddr, uint64_t Size ,
1806
1820
Align ShadowAlign,
1807
1821
Instruction *Pos) {
@@ -1959,6 +1973,23 @@ Value *DFSanFunction::loadShadow(Value *Addr, uint64_t Size, uint64_t Align,
1959
1973
return FallbackCall;
1960
1974
}
1961
1975
1976
+ static AtomicOrdering addAcquireOrdering (AtomicOrdering AO) {
1977
+ switch (AO) {
1978
+ case AtomicOrdering::NotAtomic:
1979
+ return AtomicOrdering::NotAtomic;
1980
+ case AtomicOrdering::Unordered:
1981
+ case AtomicOrdering::Monotonic:
1982
+ case AtomicOrdering::Acquire:
1983
+ return AtomicOrdering::Acquire;
1984
+ case AtomicOrdering::Release:
1985
+ case AtomicOrdering::AcquireRelease:
1986
+ return AtomicOrdering::AcquireRelease;
1987
+ case AtomicOrdering::SequentiallyConsistent:
1988
+ return AtomicOrdering::SequentiallyConsistent;
1989
+ }
1990
+ llvm_unreachable (" Unknown ordering" );
1991
+ }
1992
+
1962
1993
void DFSanVisitor::visitLoadInst (LoadInst &LI) {
1963
1994
auto &DL = LI.getModule ()->getDataLayout ();
1964
1995
uint64_t Size = DL.getTypeStoreSize (LI.getType ());
@@ -1967,26 +1998,49 @@ void DFSanVisitor::visitLoadInst(LoadInst &LI) {
1967
1998
return ;
1968
1999
}
1969
2000
2001
+ // When an application load is atomic, increase atomic ordering between
2002
+ // atomic application loads and stores to ensure happen-before order; load
2003
+ // shadow data after application data; store zero shadow data before
2004
+ // application data. This ensure shadow loads return either labels of the
2005
+ // initial application data or zeros.
2006
+ if (LI.isAtomic ())
2007
+ LI.setOrdering (addAcquireOrdering (LI.getOrdering ()));
2008
+
1970
2009
Align Alignment = ClPreserveAlignment ? LI.getAlign () : Align (1 );
2010
+ Instruction *Pos = LI.isAtomic () ? LI.getNextNode () : &LI;
1971
2011
Value *PrimitiveShadow =
1972
- DFSF.loadShadow (LI.getPointerOperand (), Size , Alignment.value (), &LI );
2012
+ DFSF.loadShadow (LI.getPointerOperand (), Size , Alignment.value (), Pos );
1973
2013
if (ClCombinePointerLabelsOnLoad) {
1974
2014
Value *PtrShadow = DFSF.getShadow (LI.getPointerOperand ());
1975
- PrimitiveShadow = DFSF.combineShadows (PrimitiveShadow, PtrShadow, &LI );
2015
+ PrimitiveShadow = DFSF.combineShadows (PrimitiveShadow, PtrShadow, Pos );
1976
2016
}
1977
2017
if (!DFSF.DFS .isZeroShadow (PrimitiveShadow))
1978
2018
DFSF.NonZeroChecks .push_back (PrimitiveShadow);
1979
2019
1980
2020
Value *Shadow =
1981
- DFSF.expandFromPrimitiveShadow (LI.getType (), PrimitiveShadow, &LI );
2021
+ DFSF.expandFromPrimitiveShadow (LI.getType (), PrimitiveShadow, Pos );
1982
2022
DFSF.setShadow (&LI, Shadow);
1983
2023
if (ClEventCallbacks) {
1984
- IRBuilder<> IRB (&LI );
2024
+ IRBuilder<> IRB (Pos );
1985
2025
Value *Addr8 = IRB.CreateBitCast (LI.getPointerOperand (), DFSF.DFS .Int8Ptr );
1986
2026
IRB.CreateCall (DFSF.DFS .DFSanLoadCallbackFn , {PrimitiveShadow, Addr8});
1987
2027
}
1988
2028
}
1989
2029
2030
+ void DFSanFunction::storeZeroPrimitiveShadow (Value *Addr, uint64_t Size ,
2031
+ Align ShadowAlign,
2032
+ Instruction *Pos) {
2033
+ IRBuilder<> IRB (Pos);
2034
+ IntegerType *ShadowTy =
2035
+ IntegerType::get (*DFS.Ctx , Size * DFS.ShadowWidthBits );
2036
+ Value *ExtZeroShadow = ConstantInt::get (ShadowTy, 0 );
2037
+ Value *ShadowAddr = DFS.getShadowAddress (Addr, Pos);
2038
+ Value *ExtShadowAddr =
2039
+ IRB.CreateBitCast (ShadowAddr, PointerType::getUnqual (ShadowTy));
2040
+ IRB.CreateAlignedStore (ExtZeroShadow, ExtShadowAddr, ShadowAlign);
2041
+ // Do not write origins for 0 shadows because we do not trace origins for
2042
+ // untainted sinks.
2043
+ }
1990
2044
void DFSanFunction::storePrimitiveShadow (Value *Addr, uint64_t Size ,
1991
2045
Align Alignment,
1992
2046
Value *PrimitiveShadow,
@@ -2001,18 +2055,13 @@ void DFSanFunction::storePrimitiveShadow(Value *Addr, uint64_t Size,
2001
2055
}
2002
2056
2003
2057
const Align ShadowAlign (Alignment.value () * DFS.ShadowWidthBytes );
2004
- IRBuilder<> IRB (Pos);
2005
- Value *ShadowAddr = DFS.getShadowAddress (Addr, Pos);
2006
2058
if (DFS.isZeroShadow (PrimitiveShadow)) {
2007
- IntegerType *ShadowTy =
2008
- IntegerType::get (*DFS.Ctx , Size * DFS.ShadowWidthBits );
2009
- Value *ExtZeroShadow = ConstantInt::get (ShadowTy, 0 );
2010
- Value *ExtShadowAddr =
2011
- IRB.CreateBitCast (ShadowAddr, PointerType::getUnqual (ShadowTy));
2012
- IRB.CreateAlignedStore (ExtZeroShadow, ExtShadowAddr, ShadowAlign);
2059
+ storeZeroPrimitiveShadow (Addr, Size , ShadowAlign, Pos);
2013
2060
return ;
2014
2061
}
2015
2062
2063
+ IRBuilder<> IRB (Pos);
2064
+ Value *ShadowAddr = DFS.getShadowAddress (Addr, Pos);
2016
2065
const unsigned ShadowVecSize = 128 / DFS.ShadowWidthBits ;
2017
2066
uint64_t Offset = 0 ;
2018
2067
if (Size >= ShadowVecSize) {
@@ -2044,15 +2093,42 @@ void DFSanFunction::storePrimitiveShadow(Value *Addr, uint64_t Size,
2044
2093
}
2045
2094
}
2046
2095
2096
+ static AtomicOrdering addReleaseOrdering (AtomicOrdering AO) {
2097
+ switch (AO) {
2098
+ case AtomicOrdering::NotAtomic:
2099
+ return AtomicOrdering::NotAtomic;
2100
+ case AtomicOrdering::Unordered:
2101
+ case AtomicOrdering::Monotonic:
2102
+ case AtomicOrdering::Release:
2103
+ return AtomicOrdering::Release;
2104
+ case AtomicOrdering::Acquire:
2105
+ case AtomicOrdering::AcquireRelease:
2106
+ return AtomicOrdering::AcquireRelease;
2107
+ case AtomicOrdering::SequentiallyConsistent:
2108
+ return AtomicOrdering::SequentiallyConsistent;
2109
+ }
2110
+ llvm_unreachable (" Unknown ordering" );
2111
+ }
2112
+
2047
2113
void DFSanVisitor::visitStoreInst (StoreInst &SI) {
2048
2114
auto &DL = SI.getModule ()->getDataLayout ();
2049
- uint64_t Size = DL.getTypeStoreSize (SI.getValueOperand ()->getType ());
2115
+ Value *Val = SI.getValueOperand ();
2116
+ uint64_t Size = DL.getTypeStoreSize (Val->getType ());
2050
2117
if (Size == 0 )
2051
2118
return ;
2052
2119
2120
+ // When an application store is atomic, increase atomic ordering between
2121
+ // atomic application loads and stores to ensure happen-before order; load
2122
+ // shadow data after application data; store zero shadow data before
2123
+ // application data. This ensure shadow loads return either labels of the
2124
+ // initial application data or zeros.
2125
+ if (SI.isAtomic ())
2126
+ SI.setOrdering (addReleaseOrdering (SI.getOrdering ()));
2127
+
2053
2128
const Align Alignment = ClPreserveAlignment ? SI.getAlign () : Align (1 );
2054
2129
2055
- Value* Shadow = DFSF.getShadow (SI.getValueOperand ());
2130
+ Value *Shadow =
2131
+ SI.isAtomic () ? DFSF.DFS .getZeroShadow (Val) : DFSF.getShadow (Val);
2056
2132
Value *PrimitiveShadow;
2057
2133
if (ClCombinePointerLabelsOnStore) {
2058
2134
Value *PtrShadow = DFSF.getShadow (SI.getPointerOperand ());
@@ -2069,6 +2145,38 @@ void DFSanVisitor::visitStoreInst(StoreInst &SI) {
2069
2145
}
2070
2146
}
2071
2147
2148
+ void DFSanVisitor::visitCASOrRMW (Align InstAlignment, Instruction &I) {
2149
+ assert (isa<AtomicRMWInst>(I) || isa<AtomicCmpXchgInst>(I));
2150
+
2151
+ Value *Val = I.getOperand (1 );
2152
+ const auto &DL = I.getModule ()->getDataLayout ();
2153
+ uint64_t Size = DL.getTypeStoreSize (Val->getType ());
2154
+ if (Size == 0 )
2155
+ return ;
2156
+
2157
+ // Conservatively set data at stored addresses and return with zero shadow to
2158
+ // prevent shadow data races.
2159
+ IRBuilder<> IRB (&I);
2160
+ Value *Addr = I.getOperand (0 );
2161
+ const Align ShadowAlign = DFSF.getShadowAlign (InstAlignment);
2162
+ DFSF.storeZeroPrimitiveShadow (Addr, Size , ShadowAlign, &I);
2163
+ DFSF.setShadow (&I, DFSF.DFS .getZeroShadow (&I));
2164
+ }
2165
+
2166
+ void DFSanVisitor::visitAtomicRMWInst (AtomicRMWInst &I) {
2167
+ visitCASOrRMW (I.getAlign (), I);
2168
+ // TODO: The ordering change follows MSan. It is possible not to change
2169
+ // ordering because we always set and use 0 shadows.
2170
+ I.setOrdering (addReleaseOrdering (I.getOrdering ()));
2171
+ }
2172
+
2173
+ void DFSanVisitor::visitAtomicCmpXchgInst (AtomicCmpXchgInst &I) {
2174
+ visitCASOrRMW (I.getAlign (), I);
2175
+ // TODO: The ordering change follows MSan. It is possible not to change
2176
+ // ordering because we always set and use 0 shadows.
2177
+ I.setSuccessOrdering (addReleaseOrdering (I.getSuccessOrdering ()));
2178
+ }
2179
+
2072
2180
void DFSanVisitor::visitUnaryOperator (UnaryOperator &UO) {
2073
2181
visitInstOperands (UO);
2074
2182
}
0 commit comments