blob: f3300d6090fad9f9ae6d6a1277610f47acaf49eb [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
Elliott Hughescbc80ba2018-02-13 14:26:29 -080029#pragma once
Evgenii Stepanov0a3637d2016-07-06 13:20:59 -070030
31#include "linker.h"
32#include "linker_debug.h"
33
34#include <algorithm>
35
36#include "private/CFIShadow.h"
37
38// This class keeps the contents of CFI shadow up-to-date with the current set of loaded libraries.
39// See the comment in CFIShadow.h for more context.
40// See documentation in http://clang.llvm.org/docs/ControlFlowIntegrityDesign.html#shared-library-support.
41//
42// Shadow is mapped and initialized lazily as soon as the first CFI-enabled DSO is loaded.
Evgenii Stepanov636a2ec2017-01-20 13:47:04 -080043// It is updated after any library is loaded (but before any constructors are ran), and
Evgenii Stepanov0a3637d2016-07-06 13:20:59 -070044// before any library is unloaded.
45class CFIShadowWriter : private CFIShadow {
46 // Returns pointer to the shadow element for an address.
47 uint16_t* MemToShadow(uintptr_t x) {
48 return reinterpret_cast<uint16_t*>(*shadow_start + MemToShadowOffset(x));
49 }
50
51 // Update shadow for the address range to the given constant value.
52 void AddConstant(uintptr_t begin, uintptr_t end, uint16_t v);
53
54 // Update shadow for the address range to kUncheckedShadow.
55 void AddUnchecked(uintptr_t begin, uintptr_t end);
56
57 // Update shadow for the address range to kInvalidShadow.
58 void AddInvalid(uintptr_t begin, uintptr_t end);
59
60 // Update shadow for the address range to the given __cfi_check value.
61 void Add(uintptr_t begin, uintptr_t end, uintptr_t cfi_check);
62
63 // Add a DSO to CFI shadow.
64 bool AddLibrary(soinfo* si);
65
66 // Map CFI shadow.
67 uintptr_t MapShadow();
68
69 // Initialize CFI shadow and update its contents for everything in solist if any loaded library is
Evgenii Stepanov636a2ec2017-01-20 13:47:04 -080070 // CFI-enabled. If new_si != nullptr, do an incremental check by looking only at new_si; otherwise
71 // look at the entire solist.
Evgenii Stepanov0a3637d2016-07-06 13:20:59 -070072 bool MaybeInit(soinfo *new_si, soinfo *solist);
73
74 // Set a human readable name for the entire shadow region.
75 void FixupVmaName();
76
Evgenii Stepanov636a2ec2017-01-20 13:47:04 -080077 // Pass the pointer to the mapped shadow region to libdl. Must only be called once.
78 // Flips shadow_start to a non-nullptr value.
Evgenii Stepanov0a3637d2016-07-06 13:20:59 -070079 bool NotifyLibDl(soinfo *solist, uintptr_t p);
80
81 // Pointer to the shadow start address.
82 uintptr_t *shadow_start;
83
84 bool initial_link_done;
85
86 public:
Evgenii Stepanov636a2ec2017-01-20 13:47:04 -080087 // Update shadow after loading a DSO.
Evgenii Stepanov0a3637d2016-07-06 13:20:59 -070088 // This function will initialize the shadow if it sees a CFI-enabled DSO for the first time.
89 // In that case it will retroactively update shadow for all previously loaded DSOs. "solist" is a
90 // pointer to the global list.
91 // This function must be called before any user code has observed the newly loaded DSO.
92 bool AfterLoad(soinfo* si, soinfo *solist);
93
94 // Update shadow before unloading a DSO.
95 void BeforeUnload(soinfo* si);
96
Evgenii Stepanov636a2ec2017-01-20 13:47:04 -080097 // This is called as soon as the initial set of libraries is linked.
Evgenii Stepanov0a3637d2016-07-06 13:20:59 -070098 bool InitialLinkDone(soinfo *solist);
99
100 // Handle failure to locate __cfi_check for a target address.
101 static void CfiFail(uint64_t CallSiteTypeId, void* Ptr, void* DiagData, void *caller_pc);
102};
103
104CFIShadowWriter* get_cfi_shadow();