aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--src/conflict.c51
-rw-r--r--src/undo.c9
3 files changed, 51 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index 1faef5e..e4770f6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,8 @@
2018-10-12 Kyle Russell <bkylerussell@gmail.com>
+ * src/conflict.c, src/undo.c: Add knowledge of .data.rel.ro for
+ read-only dynamic symbols
+
+2018-10-12 Kyle Russell <bkylerussell@gmail.com>
* src/rtld/dl-lookupX.h: Fix rtld segfault when _dl_lookup_symbol_x
is NULL on protected symbol relocations
* testsuite/Makefile.am, testsuite/reloc12.c, testsuite/reloc12.h,
diff --git a/src/conflict.c b/src/conflict.c
index 9ae2ddb..5613ace 100644
--- a/src/conflict.c
+++ b/src/conflict.c
@@ -450,7 +450,7 @@ get_relocated_mem (struct prelink_info *info, DSO *dso, GElf_Addr addr,
int
prelink_build_conflicts (struct prelink_info *info)
{
- int i, ndeps = info->ent->ndepends + 1;
+ int i, reset_dynbss = 0, reset_sdynbss = 0, ndeps = info->ent->ndepends + 1;
struct prelink_entry *ent;
int ret = 0;
DSO *dso;
@@ -675,6 +675,11 @@ prelink_build_conflicts (struct prelink_info *info)
dso->filename);
goto error_out;
}
+
+ name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[bss1].sh_name);
+ if (strcmp(name, ".data.rel.ro") == 0)
+ reset_sdynbss = 1;
+
firstbss2 = i;
info->sdynbss_size = cr.rela[i - 1].r_offset - cr.rela[0].r_offset;
info->sdynbss_size += cr.rela[i - 1].r_addend;
@@ -702,6 +707,10 @@ prelink_build_conflicts (struct prelink_info *info)
}
}
+ name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[bss2].sh_name);
+ if (strcmp(name, ".data.rel.ro") == 0)
+ reset_dynbss = 1;
+
info->dynbss_size = cr.rela[cr.count - 1].r_offset
- cr.rela[firstbss2].r_offset;
info->dynbss_size += cr.rela[cr.count - 1].r_addend;
@@ -719,9 +728,9 @@ prelink_build_conflicts (struct prelink_info *info)
&& strcmp (name = strptr (dso, dso->ehdr.e_shstrndx,
dso->shdr[bss1].sh_name),
".dynbss") != 0
- && strcmp (name, ".sdynbss") != 0)
+ && strcmp (name, ".sdynbss") != 0 && strcmp (name, ".data.rel.ro") != 0)
{
- error (0, 0, "%s: COPY relocations don't point into .bss or .sbss section",
+ error (0, 0, "%s: COPY relocations don't point into .bss, .sbss, or .data.rel.ro sections",
dso->filename);
goto error_out;
}
@@ -730,9 +739,9 @@ prelink_build_conflicts (struct prelink_info *info)
&& strcmp (name = strptr (dso, dso->ehdr.e_shstrndx,
dso->shdr[bss2].sh_name),
".dynbss") != 0
- && strcmp (name, ".sdynbss") != 0)
+ && strcmp (name, ".sdynbss") != 0 && strcmp (name, ".data.rel.ro") != 0)
{
- error (0, 0, "%s: COPY relocations don't point into .bss or .sbss section",
+ error (0, 0, "%s: COPY relocations don't point into .bss, .sbss, or .data.rel.ro section",
dso->filename);
goto error_out;
}
@@ -768,16 +777,21 @@ prelink_build_conflicts (struct prelink_info *info)
}
assert (j < ndeps);
+ GElf_Addr symaddr = s->u.ent->base + s->value;
+ char *buf;
+
if (i < firstbss2)
- j = get_relocated_mem (info, ndso, s->u.ent->base + s->value,
- info->sdynbss + cr.rela[i].r_offset
- - info->sdynbss_base, cr.rela[i].r_addend,
- cr.rela[i].r_offset);
+ if (reset_sdynbss)
+ buf = get_data(dso, cr.rela[i].r_offset, NULL, NULL);
+ else
+ buf = info->sdynbss + cr.rela[i].r_offset - info->sdynbss_base;
else
- j = get_relocated_mem (info, ndso, s->u.ent->base + s->value,
- info->dynbss + cr.rela[i].r_offset
- - info->dynbss_base, cr.rela[i].r_addend,
- cr.rela[i].r_offset);
+ if (reset_dynbss)
+ buf = get_data(dso, cr.rela[i].r_offset, NULL, NULL);
+ else
+ buf = info->dynbss + cr.rela[i].r_offset - info->dynbss_base;
+
+ j = get_relocated_mem (info, ndso, symaddr, buf, cr.rela[i].r_addend, cr.rela[i].r_offset);
switch (j)
{
@@ -815,6 +829,17 @@ prelink_build_conflicts (struct prelink_info *info)
if (info->dsos[i])
close_dso (info->dsos[i]);
+ if (reset_sdynbss)
+ {
+ free (info->sdynbss);
+ info->sdynbss = NULL;
+ }
+
+ if (reset_dynbss)
+ {
+ free (info->dynbss);
+ info->dynbss = NULL;
+ }
info->dsos = NULL;
free (cr.rela);
return ret;
diff --git a/src/undo.c b/src/undo.c
index 8a55bf2..4c38dab 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -633,6 +633,15 @@ prelink_undo (DSO *dso)
d->d_buf = NULL;
dso->shdr[i].sh_type = SHT_NOBITS;
}
+ else if (dso->shdr[i].sh_type == SHT_PROGBITS
+ && strcmp (name, ".data.rel.ro") == 0)
+ {
+ scn = dso->scn[i];
+ d = elf_getdata (scn, NULL);
+ assert (d != NULL && elf_getdata (scn, d) == NULL);
+ assert (d->d_size == dso->shdr[i].sh_size);
+ assert (memset(d->d_buf, 0, d->d_size) == d->d_buf);
+ }
else if (dso->shdr[i].sh_type == SHT_RELA
&& shdr[i].sh_type == SHT_REL)
{