blob: e54554f77fe6c915751515973f4fb347eab38ea2 [file] [log] [blame]
Evgenii Stepanov0a3637d2016-07-06 13:20:59 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
Dimitry Ivanovbcc4da92017-02-15 15:31:13 -08003 * All rights reserved.
Evgenii Stepanov0a3637d2016-07-06 13:20:59 -07004 *
Dimitry Ivanovbcc4da92017-02-15 15:31:13 -08005 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
Evgenii Stepanov0a3637d2016-07-06 13:20:59 -070014 *
Dimitry Ivanovbcc4da92017-02-15 15:31:13 -080015 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
Evgenii Stepanov0a3637d2016-07-06 13:20:59 -070027 */
28
29#ifndef _LINKER_CFI_H_
30#define _LINKER_CFI_H_
31
32#include "linker.h"
33#include "linker_debug.h"
34
35#include <algorithm>
36
37#include "private/CFIShadow.h"
38
39// This class keeps the contents of CFI shadow up-to-date with the current set of loaded libraries.
40// See the comment in CFIShadow.h for more context.
41// See documentation in http://clang.llvm.org/docs/ControlFlowIntegrityDesign.html#shared-library-support.
42//
43// Shadow is mapped and initialized lazily as soon as the first CFI-enabled DSO is loaded.
Evgenii Stepanov636a2ec2017-01-20 13:47:04 -080044// It is updated after any library is loaded (but before any constructors are ran), and
Evgenii Stepanov0a3637d2016-07-06 13:20:59 -070045// before any library is unloaded.
46class CFIShadowWriter : private CFIShadow {
47 // Returns pointer to the shadow element for an address.
48 uint16_t* MemToShadow(uintptr_t x) {
49 return reinterpret_cast<uint16_t*>(*shadow_start + MemToShadowOffset(x));
50 }
51
52 // Update shadow for the address range to the given constant value.
53 void AddConstant(uintptr_t begin, uintptr_t end, uint16_t v);
54
55 // Update shadow for the address range to kUncheckedShadow.
56 void AddUnchecked(uintptr_t begin, uintptr_t end);
57
58 // Update shadow for the address range to kInvalidShadow.
59 void AddInvalid(uintptr_t begin, uintptr_t end);
60
61 // Update shadow for the address range to the given __cfi_check value.
62 void Add(uintptr_t begin, uintptr_t end, uintptr_t cfi_check);
63
64 // Add a DSO to CFI shadow.
65 bool AddLibrary(soinfo* si);
66
67 // Map CFI shadow.
68 uintptr_t MapShadow();
69
70 // Initialize CFI shadow and update its contents for everything in solist if any loaded library is
Evgenii Stepanov636a2ec2017-01-20 13:47:04 -080071 // CFI-enabled. If new_si != nullptr, do an incremental check by looking only at new_si; otherwise
72 // look at the entire solist.
Evgenii Stepanov0a3637d2016-07-06 13:20:59 -070073 bool MaybeInit(soinfo *new_si, soinfo *solist);
74
75 // Set a human readable name for the entire shadow region.
76 void FixupVmaName();
77
Evgenii Stepanov636a2ec2017-01-20 13:47:04 -080078 // Pass the pointer to the mapped shadow region to libdl. Must only be called once.
79 // Flips shadow_start to a non-nullptr value.
Evgenii Stepanov0a3637d2016-07-06 13:20:59 -070080 bool NotifyLibDl(soinfo *solist, uintptr_t p);
81
82 // Pointer to the shadow start address.
83 uintptr_t *shadow_start;
84
85 bool initial_link_done;
86
87 public:
Evgenii Stepanov636a2ec2017-01-20 13:47:04 -080088 // Update shadow after loading a DSO.
Evgenii Stepanov0a3637d2016-07-06 13:20:59 -070089 // This function will initialize the shadow if it sees a CFI-enabled DSO for the first time.
90 // In that case it will retroactively update shadow for all previously loaded DSOs. "solist" is a
91 // pointer to the global list.
92 // This function must be called before any user code has observed the newly loaded DSO.
93 bool AfterLoad(soinfo* si, soinfo *solist);
94
95 // Update shadow before unloading a DSO.
96 void BeforeUnload(soinfo* si);
97
Evgenii Stepanov636a2ec2017-01-20 13:47:04 -080098 // This is called as soon as the initial set of libraries is linked.
Evgenii Stepanov0a3637d2016-07-06 13:20:59 -070099 bool InitialLinkDone(soinfo *solist);
100
101 // Handle failure to locate __cfi_check for a target address.
102 static void CfiFail(uint64_t CallSiteTypeId, void* Ptr, void* DiagData, void *caller_pc);
103};
104
105CFIShadowWriter* get_cfi_shadow();
106
107#endif // _LINKER_CFI_H_