Introducing Integrity audit functions.
[WebKit-https.git] / Source / JavaScriptCore / tools / IntegrityInlines.h
1 /*
2  * Copyright (C) 2019 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #include "Integrity.h"
29 #include "VM.h"
30
31 namespace JSC {
32 namespace Integrity {
33
34 ALWAYS_INLINE bool Random::shouldAudit(VM& vm)
35 {
36     // If auditing is enabled, then the top bit of m_triggerBits is always set
37     // to 1 on reload. When this top bit reaches the bottom, it does not
38     // indicate that we should trigger an audit but rather that we've shifted
39     // out all the available trigger bits and hence, need to reload. Instead,
40     // reloadAndCheckShouldAuditSlow() will return whether we actually need to
41     // trigger an audit this turn.
42     //
43     // This function can be called concurrently from different threads and can
44     // be racy. For that reason, we intentionally do not write back to
45     // m_triggerBits if newTriggerBits is null. This ensures that if
46     // Options::randomIntegrityAuditRate() is non-zero, then m_triggerBits will
47     // always have at least 1 bit to trigger a reload.
48
49     uint64_t newTriggerBits = m_triggerBits;
50     bool shouldAudit = newTriggerBits & 1;
51     newTriggerBits = newTriggerBits >> 1;
52     if (LIKELY(!shouldAudit)) {
53         m_triggerBits = newTriggerBits;
54         return false;
55     }
56
57     if (!newTriggerBits)
58         return reloadAndCheckShouldAuditSlow(vm);
59
60     m_triggerBits = newTriggerBits;
61     return true;
62 }
63
64 ALWAYS_INLINE void auditCellMinimally(VM& vm, JSCell* cell)
65 {
66     if (UNLIKELY(Gigacage::contains(cell)))
67         auditCellMinimallySlow(vm, cell);
68 }
69
70 ALWAYS_INLINE void auditCellRandomly(VM& vm, JSCell* cell)
71 {
72     if (UNLIKELY(vm.integrityRandom().shouldAudit(vm)))
73         auditCellFully(vm, cell);
74 }
75
76 } // namespace Integrity
77 } // namespace JSC