aboutsummaryrefslogtreecommitdiff
path: root/sbin/ldconfig/elfhints.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/ldconfig/elfhints.c')
-rw-r--r--sbin/ldconfig/elfhints.c46
1 files changed, 32 insertions, 14 deletions
diff --git a/sbin/ldconfig/elfhints.c b/sbin/ldconfig/elfhints.c
index 72b9273ab93a..97499e398c9d 100644
--- a/sbin/ldconfig/elfhints.c
+++ b/sbin/ldconfig/elfhints.c
@@ -27,6 +27,7 @@
*/
#include <sys/param.h>
+#include <sys/endian.h>
#include <sys/mman.h>
#include <sys/stat.h>
@@ -48,11 +49,12 @@
static void add_dir(const char *, const char *, bool);
static void read_dirs_from_file(const char *, const char *);
-static void read_elf_hints(const char *, bool);
+static void read_elf_hints(const char *, bool, bool);
static void write_elf_hints(const char *);
static const char *dirs[MAXDIRS];
static int ndirs;
+static bool is_be;
bool insecure;
static void
@@ -95,7 +97,7 @@ list_elf_hints(const char *hintsfile)
int i;
int nlibs;
- read_elf_hints(hintsfile, 1);
+ read_elf_hints(hintsfile, true, false);
printf("%s:\n", hintsfile);
printf("\tsearch directories:");
for (i = 0; i < ndirs; i++)
@@ -183,8 +185,11 @@ read_dirs_from_file(const char *hintsfile, const char *listfile)
fclose(fp);
}
+/* Convert between native byte order and forced little resp. big endian. */
+#define COND_SWAP(n) (is_be ? be32toh(n) : le32toh(n))
+
static void
-read_elf_hints(const char *hintsfile, bool must_exist)
+read_elf_hints(const char *hintsfile, bool must_exist, bool force_be)
{
int fd;
struct stat s;
@@ -193,6 +198,7 @@ read_elf_hints(const char *hintsfile, bool must_exist)
char *strtab;
char *dirlist;
char *p;
+ int hdr_version;
if ((fd = open(hintsfile, O_RDONLY)) == -1) {
if (errno == ENOENT && !must_exist)
@@ -214,14 +220,18 @@ read_elf_hints(const char *hintsfile, bool must_exist)
close(fd);
hdr = (struct elfhints_hdr *)mapbase;
- if (hdr->magic != ELFHINTS_MAGIC)
+ is_be = hdr->magic == htobe32(ELFHINTS_MAGIC);
+ if (COND_SWAP(hdr->magic) != ELFHINTS_MAGIC)
errx(1, "\"%s\": invalid file format", hintsfile);
- if (hdr->version != 1)
+ if (force_be && !is_be)
+ errx(1, "\"%s\": incompatible endianness requested", hintsfile);
+ hdr_version = COND_SWAP(hdr->version);
+ if (hdr_version != 1)
errx(1, "\"%s\": unrecognized file version (%d)", hintsfile,
- hdr->version);
+ hdr_version);
- strtab = (char *)mapbase + hdr->strtab;
- dirlist = strtab + hdr->dirlist;
+ strtab = (char *)mapbase + COND_SWAP(hdr->strtab);
+ dirlist = strtab + COND_SWAP(hdr->dirlist);
if (*dirlist != '\0')
while ((p = strsep(&dirlist, ":")) != NULL)
@@ -229,13 +239,19 @@ read_elf_hints(const char *hintsfile, bool must_exist)
}
void
-update_elf_hints(const char *hintsfile, int argc, char **argv, bool merge)
+update_elf_hints(const char *hintsfile, int argc, char **argv, bool merge,
+ bool force_be)
{
struct stat s;
int i;
+ /*
+ * Create little-endian hints files on all architectures unless
+ * ldconfig has been invoked with the -B option.
+ */
+ is_be = force_be;
if (merge)
- read_elf_hints(hintsfile, false);
+ read_elf_hints(hintsfile, false, force_be);
for (i = 0; i < argc; i++) {
if (stat(argv[i], &s) == -1)
warn("warning: %s", argv[i]);
@@ -265,9 +281,9 @@ write_elf_hints(const char *hintsfile)
if ((fp = fdopen(fd, "wb")) == NULL)
err(1, "fdopen(%s)", tempname);
- hdr.magic = ELFHINTS_MAGIC;
- hdr.version = 1;
- hdr.strtab = sizeof hdr;
+ hdr.magic = COND_SWAP(ELFHINTS_MAGIC);
+ hdr.version = COND_SWAP(1);
+ hdr.strtab = COND_SWAP(sizeof hdr);
hdr.strsize = 0;
hdr.dirlist = 0;
memset(hdr.spare, 0, sizeof hdr.spare);
@@ -278,8 +294,10 @@ write_elf_hints(const char *hintsfile)
for (i = 1; i < ndirs; i++)
hdr.strsize += 1 + strlen(dirs[i]);
}
- hdr.dirlistlen = hdr.strsize;
+ hdr.dirlistlen = COND_SWAP(hdr.strsize);
hdr.strsize++; /* For the null terminator */
+ /* convert in-place from native to target endianness */
+ hdr.strsize = COND_SWAP(hdr.strsize);
/* Write the header. */
if (fwrite(&hdr, 1, sizeof hdr, fp) != sizeof hdr)