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