1cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner// Use of this source code is governed by a BSD-style license that can be
3cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner// found in the LICENSE file.
4cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner
5cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner#ifndef CRAZY_LINKER_ELF_RELRO_H
6cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner#define CRAZY_LINKER_ELF_RELRO_H
7cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner
8cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner#include "crazy_linker_ashmem.h"
9cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner#include "crazy_linker_memory_mapping.h"
1041051de2c8fbb9c59b436f221544b2b22a93a034David 'Digit' Turner#include "crazy_linker_system.h"
11cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner#include "elf_traits.h"
12cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner
13cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turnernamespace crazy {
14cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner
15cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turnerclass ElfView;
16cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner
17cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner// A class used to model a shared RELRO section backed by an Ashmem region.
18cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner// The region is always owned by the SharedRelro, unless DetachFd() is called.
19cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner// The SharedRelro may or may not be mapped into the process.
20cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turnerclass SharedRelro {
21cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner public:
22cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // Create a new SharedRelro. Note that the object becomes the owner of
23cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // |ashmem_fd|, unless DetachFd() is called after this.
24cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  SharedRelro() : start_(0), size_(0), ashmem_() {}
25cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner
26cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  ~SharedRelro() {}
27cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner
28cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  size_t start() const { return start_; }
29cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  size_t end() const { return start_ + size_; }
30cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  size_t size() const { return size_; }
31cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  int fd() const { return ashmem_.fd(); }
32cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner
33cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // Return the ashmem region's file descriptor, and detach it from the object.
34cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // After this call, fd() will always return -1.
3541051de2c8fbb9c59b436f221544b2b22a93a034David 'Digit' Turner  int DetachFd() { return ashmem_.Release(); }
36cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner
37cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // Allocate a new ashmem region of |relro_size| bytes for |library_name|.
38cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // This operation doesn't change the process' mappings. On error, return
39cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // false and set |error| message.
4041051de2c8fbb9c59b436f221544b2b22a93a034David 'Digit' Turner  bool Allocate(size_t relro_size, const char* library_name, Error* error);
41cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner
42cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // Copy the content of the current process' RELRO into the ashmem region.
43cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // |relro_start| is the RELRO address (page-aligned).
44cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // |relro_size| is the RELRO size in bytes (page-aligned), and must match
45cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // the allocation size passed to Allocate().
46cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // On failure, return false and set |error| message.
4741051de2c8fbb9c59b436f221544b2b22a93a034David 'Digit' Turner  bool CopyFrom(size_t relro_start, size_t relro_size, Error* error);
48cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner
49cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // Copy the contents of the current process' RELRO into the ashmem region
50cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // but adjust any relocation targets within it to correspond to a new
51cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // |load_address|. |view| must point to a mapped ELF binary for the current
52cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // library. |relro_start| corresponds to the address of the current
53cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // process' RELRO, i.e. is not relocated.
54cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  bool CopyFromRelocated(const ElfView* view,
55cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner                         size_t load_address,
56cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner                         size_t relro_start,
57cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner                         size_t relro_size,
58cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner                         Error* error);
59cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner
60cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // Force the section to be read-only.
61cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  bool ForceReadOnly(Error* error);
62cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner
63cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // Map the ashmem region's pages into the current process, doing a comparison
64cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // to avoid corrupting parts of the RELRO section that are different in this
65cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // one (e.g. due to symbolic relocations to randomized system libraries).
66cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // This operation is _not_ atomic, i.e. no other thread should try to execute
67cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // code that reads from the RELRO region during this call.
68cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // On failure, return false and set |error| message.
69cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  // This operation does not transfer ownership of |ashmem_fd| to the object.
70cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  bool InitFrom(size_t relro_start,
71cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner                size_t relro_size,
72cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner                int ashmem_fd,
73cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner                Error* error);
74cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner
75cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner private:
76cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  size_t start_;
77cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  size_t size_;
78cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner  AshmemRegion ashmem_;
79cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner};
80cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner
81cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner}  // namespace crazy
82cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner
83cc87d1d56b0e1cef0131d9193c702d528417b61aDavid 'Digit' Turner#endif  // CRAZY_LINKER_ELF_RELRO_H
84