am 61a35fa4: Merge "Remove text-relocation support for lp32"
				
					
				
			* commit '61a35fa40c898dc08c28c9da8b174ba5d5614579': Remove text-relocation support for lp32
This commit is contained in:
		@@ -2297,13 +2297,8 @@ bool soinfo::prelink_image() {
 | 
				
			|||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case DT_TEXTREL:
 | 
					      case DT_TEXTREL:
 | 
				
			||||||
#if defined(__LP64__)
 | 
					        DL_ERR("text relocations (DT_TEXTREL) found in the ELF file \"%s\"", name);
 | 
				
			||||||
        DL_ERR("text relocations (DT_TEXTREL) found in 64-bit ELF file \"%s\"", name);
 | 
					 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
        has_text_relocations = true;
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case DT_SYMBOLIC:
 | 
					      case DT_SYMBOLIC:
 | 
				
			||||||
        has_DT_SYMBOLIC = true;
 | 
					        has_DT_SYMBOLIC = true;
 | 
				
			||||||
@@ -2315,12 +2310,8 @@ bool soinfo::prelink_image() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      case DT_FLAGS:
 | 
					      case DT_FLAGS:
 | 
				
			||||||
        if (d->d_un.d_val & DF_TEXTREL) {
 | 
					        if (d->d_un.d_val & DF_TEXTREL) {
 | 
				
			||||||
#if defined(__LP64__)
 | 
					          DL_ERR("text relocations (DF_TEXTREL) found in the ELF file \"%s\"", name);
 | 
				
			||||||
          DL_ERR("text relocations (DF_TEXTREL) found in 64-bit ELF file \"%s\"", name);
 | 
					 | 
				
			||||||
          return false;
 | 
					          return false;
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
          has_text_relocations = true;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (d->d_un.d_val & DF_SYMBOLIC) {
 | 
					        if (d->d_un.d_val & DF_SYMBOLIC) {
 | 
				
			||||||
          has_DT_SYMBOLIC = true;
 | 
					          has_DT_SYMBOLIC = true;
 | 
				
			||||||
@@ -2429,20 +2420,6 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t&
 | 
				
			|||||||
    local_group_root_ = this;
 | 
					    local_group_root_ = this;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if !defined(__LP64__)
 | 
					 | 
				
			||||||
  if (has_text_relocations) {
 | 
					 | 
				
			||||||
    // Make segments writable to allow text relocations to work properly. We will later call
 | 
					 | 
				
			||||||
    // phdr_table_protect_segments() after all of them are applied and all constructors are run.
 | 
					 | 
				
			||||||
    DL_WARN("%s has text relocations. This is wasting memory and prevents "
 | 
					 | 
				
			||||||
            "security hardening. Please fix.", name);
 | 
					 | 
				
			||||||
    if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
 | 
					 | 
				
			||||||
      DL_ERR("can't unprotect loadable segments for \"%s\": %s",
 | 
					 | 
				
			||||||
             name, strerror(errno));
 | 
					 | 
				
			||||||
      return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (android_relocs_ != nullptr) {
 | 
					  if (android_relocs_ != nullptr) {
 | 
				
			||||||
    // check signature
 | 
					    // check signature
 | 
				
			||||||
    if (android_relocs_size_ > 3 &&
 | 
					    if (android_relocs_size_ > 3 &&
 | 
				
			||||||
@@ -2513,17 +2490,6 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t&
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  DEBUG("[ finished linking %s ]", name);
 | 
					  DEBUG("[ finished linking %s ]", name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if !defined(__LP64__)
 | 
					 | 
				
			||||||
  if (has_text_relocations) {
 | 
					 | 
				
			||||||
    // All relocations are done, we can protect our segments back to read-only.
 | 
					 | 
				
			||||||
    if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
 | 
					 | 
				
			||||||
      DL_ERR("can't protect segments for \"%s\": %s",
 | 
					 | 
				
			||||||
             name, strerror(errno));
 | 
					 | 
				
			||||||
      return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* We can also turn on GNU RELRO protection */
 | 
					  /* We can also turn on GNU RELRO protection */
 | 
				
			||||||
  if (phdr_table_protect_gnu_relro(phdr, phnum, load_bias) < 0) {
 | 
					  if (phdr_table_protect_gnu_relro(phdr, phnum, load_bias) < 0) {
 | 
				
			||||||
    DL_ERR("can't enable GNU RELRO protection for \"%s\": %s",
 | 
					    DL_ERR("can't enable GNU RELRO protection for \"%s\": %s",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -226,8 +226,8 @@ struct soinfo {
 | 
				
			|||||||
  // value to get the corresponding address in the process' address space.
 | 
					  // value to get the corresponding address in the process' address space.
 | 
				
			||||||
  ElfW(Addr) load_bias;
 | 
					  ElfW(Addr) load_bias;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if !defined(__LP64__)
 | 
					#if defined(__arm__)
 | 
				
			||||||
  bool has_text_relocations;
 | 
					  bool unused4; // DO NOT USE, maintained for compatibility
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  bool has_DT_SYMBOLIC;
 | 
					  bool has_DT_SYMBOLIC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -412,70 +412,6 @@ bool ElfReader::LoadSegments() {
 | 
				
			|||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Used internally. Used to set the protection bits of all loaded segments
 | 
					 | 
				
			||||||
 * with optional extra flags (i.e. really PROT_WRITE). Used by
 | 
					 | 
				
			||||||
 * phdr_table_protect_segments and phdr_table_unprotect_segments.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static int _phdr_table_set_load_prot(const ElfW(Phdr)* phdr_table, size_t phdr_count,
 | 
					 | 
				
			||||||
                                     ElfW(Addr) load_bias, int extra_prot_flags) {
 | 
					 | 
				
			||||||
  const ElfW(Phdr)* phdr = phdr_table;
 | 
					 | 
				
			||||||
  const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  for (; phdr < phdr_limit; phdr++) {
 | 
					 | 
				
			||||||
    if (phdr->p_type != PT_LOAD || (phdr->p_flags & PF_W) != 0) {
 | 
					 | 
				
			||||||
      continue;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
 | 
					 | 
				
			||||||
    ElfW(Addr) seg_page_end   = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    int ret = mprotect(reinterpret_cast<void*>(seg_page_start),
 | 
					 | 
				
			||||||
                       seg_page_end - seg_page_start,
 | 
					 | 
				
			||||||
                       PFLAGS_TO_PROT(phdr->p_flags) | extra_prot_flags);
 | 
					 | 
				
			||||||
    if (ret < 0) {
 | 
					 | 
				
			||||||
      return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Restore the original protection modes for all loadable segments.
 | 
					 | 
				
			||||||
 * You should only call this after phdr_table_unprotect_segments and
 | 
					 | 
				
			||||||
 * applying all relocations.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Input:
 | 
					 | 
				
			||||||
 *   phdr_table  -> program header table
 | 
					 | 
				
			||||||
 *   phdr_count  -> number of entries in tables
 | 
					 | 
				
			||||||
 *   load_bias   -> load bias
 | 
					 | 
				
			||||||
 * Return:
 | 
					 | 
				
			||||||
 *   0 on error, -1 on failure (error code in errno).
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table,
 | 
					 | 
				
			||||||
                                size_t phdr_count, ElfW(Addr) load_bias) {
 | 
					 | 
				
			||||||
  return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Change the protection of all loaded segments in memory to writable.
 | 
					 | 
				
			||||||
 * This is useful before performing relocations. Once completed, you
 | 
					 | 
				
			||||||
 * will have to call phdr_table_protect_segments to restore the original
 | 
					 | 
				
			||||||
 * protection flags on all segments.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Note that some writable segments can also have their content turned
 | 
					 | 
				
			||||||
 * to read-only by calling phdr_table_protect_gnu_relro. This is no
 | 
					 | 
				
			||||||
 * performed here.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Input:
 | 
					 | 
				
			||||||
 *   phdr_table  -> program header table
 | 
					 | 
				
			||||||
 *   phdr_count  -> number of entries in tables
 | 
					 | 
				
			||||||
 *   load_bias   -> load bias
 | 
					 | 
				
			||||||
 * Return:
 | 
					 | 
				
			||||||
 *   0 on error, -1 on failure (error code in errno).
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table,
 | 
					 | 
				
			||||||
                                  size_t phdr_count, ElfW(Addr) load_bias) {
 | 
					 | 
				
			||||||
  return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, PROT_WRITE);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Used internally by phdr_table_protect_gnu_relro and
 | 
					/* Used internally by phdr_table_protect_gnu_relro and
 | 
				
			||||||
 * phdr_table_unprotect_gnu_relro.
 | 
					 * phdr_table_unprotect_gnu_relro.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -84,12 +84,6 @@ class ElfReader {
 | 
				
			|||||||
size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count,
 | 
					size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count,
 | 
				
			||||||
                                ElfW(Addr)* min_vaddr = nullptr, ElfW(Addr)* max_vaddr = nullptr);
 | 
					                                ElfW(Addr)* min_vaddr = nullptr, ElfW(Addr)* max_vaddr = nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table,
 | 
					 | 
				
			||||||
                                size_t phdr_count, ElfW(Addr) load_bias);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count,
 | 
					 | 
				
			||||||
                                  ElfW(Addr) load_bias);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count,
 | 
					int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count,
 | 
				
			||||||
                                 ElfW(Addr) load_bias);
 | 
					                                 ElfW(Addr) load_bias);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user