aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/dso.c10
-rw-r--r--src/main.c21
-rw-r--r--src/prelink.c5
-rw-r--r--src/prelink.h1
4 files changed, 36 insertions, 1 deletions
diff --git a/src/dso.c b/src/dso.c
index c0d70a8..d275998 100644
--- a/src/dso.c
+++ b/src/dso.c
@@ -1533,7 +1533,7 @@ close_dso (DSO *dso)
}
int
-write_dso (DSO *dso)
+prepare_write_dso (DSO *dso)
{
int i;
@@ -1551,6 +1551,14 @@ write_dso (DSO *dso)
|| dso->shdr[i].sh_type == SHT_DYNSYM)
set_stt_section_values (dso, i);
}
+ return 0;
+}
+
+int
+write_dso (DSO *dso)
+{
+ if (prepare_write_dso (dso))
+ return 1;
if (! dso->permissive && ELF_F_PERMISSIVE)
elf_flagelf (dso->elf, ELF_C_CLR, ELF_F_PERMISSIVE);
diff --git a/src/main.c b/src/main.c
index 82ee563..33e61e8 100644
--- a/src/main.c
+++ b/src/main.c
@@ -49,6 +49,7 @@ int exec_shield;
int undo, verify;
enum verify_method_t verify_method;
int quick;
+int compute_checksum;
long long seed;
GElf_Addr mmap_reg_start = ~(GElf_Addr) 0;
GElf_Addr mmap_reg_end = ~(GElf_Addr) 0;
@@ -74,6 +75,7 @@ static char argp_doc[] = "prelink -- program to relocate and prelink ELF shared
#define OPT_SEED 0x88
#define OPT_MD5 0x89
#define OPT_SHA 0x8a
+#define OPT_COMPUTE_CHECKSUM 0x8b
static struct argp_option options[] = {
{"all", 'a', 0, 0, "Prelink all binaries" },
@@ -105,6 +107,7 @@ static struct argp_option options[] = {
{"mmap-region-start", OPT_MMAP_REG_START, "BASE_ADDRESS", OPTION_HIDDEN, "" },
{"mmap-region-end", OPT_MMAP_REG_END, "BASE_ADDRESS", OPTION_HIDDEN, "" },
{"seed", OPT_SEED, "SEED", OPTION_HIDDEN, "" },
+ {"compute-checksum", OPT_COMPUTE_CHECKSUM, 0, OPTION_HIDDEN, "" },
{ 0 }
};
@@ -206,6 +209,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
case OPT_NO_EXEC_SHIELD:
exec_shield = 0;
break;
+ case OPT_COMPUTE_CHECKSUM:
+ compute_checksum = 1;
+ break;
default:
return ARGP_ERR_UNKNOWN;
}
@@ -255,6 +261,20 @@ main (int argc, char *argv[])
if (remaining == argc && ! all)
error (EXIT_FAILURE, 0, "no files given and --all not used");
+ if (compute_checksum)
+ {
+ while (remaining < argc)
+ {
+ DSO *dso = open_dso (argv[remaining++]);
+
+ if (dso == NULL || reopen_dso (dso, NULL) || prelink_set_checksum (dso))
+ error (0, 0, "could not recompute checksum of %s", dso->filename);
+ close_dso (dso);
+ error (0, 0, "%08x %s\n", (unsigned int) dso->info_DT_CHECKSUM, dso->filename);
+ }
+ exit (0);
+ }
+
if (verify)
{
if (remaining + 1 != argc)
@@ -296,6 +316,7 @@ main (int argc, char *argv[])
}
if (dynamic_info_is_set (dso, DT_CHECKSUM_BIT)
+ && dso_is_rdwr (dso)
&& prelink_set_checksum (dso))
{
++failures;
diff --git a/src/prelink.c b/src/prelink.c
index ff4728f..7bfec71 100644
--- a/src/prelink.c
+++ b/src/prelink.c
@@ -796,6 +796,11 @@ prelink_set_checksum (DSO *dso)
&& set_dynamic (dso, DT_GNU_PRELINKED, 0, 1))
return 1;
+ /* Ensure any pending .mdebug/.dynsym/.dynstr etc. modifications
+ write_dso would do happen before checksumming. */
+ if (prepare_write_dso (dso))
+ return 1;
+
cvt = ! ((__BYTE_ORDER == __LITTLE_ENDIAN
&& dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
|| (__BYTE_ORDER == __BIG_ENDIAN
diff --git a/src/prelink.h b/src/prelink.h
index c96d8d4..f9ee0f0 100644
--- a/src/prelink.h
+++ b/src/prelink.h
@@ -184,6 +184,7 @@ int adjust_mdebug (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust);
int finalize_mdebug (DSO *dso);
int relocate_dso (DSO *dso, GElf_Addr base);
int update_dso (DSO *dso);
+int prepare_write_dso (DSO *dso);
int write_dso (DSO *dso);
int close_dso (DSO *dso);
GElf_Addr adjust_old_to_new (DSO *dso, GElf_Addr addr);