X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=execute.c;h=3ed645a554a20dcedc4564ecb3e537ca2b4ef1ea;hb=802014dde0c3b25a48a4c6e5b09d20f52fb94324;hp=b102a4a2b4b4945e8cc20dc1cfeadeb43f90f789;hpb=1f4014b53a4dc77768f3998a6fd3b67024431fa3;p=fips diff --git a/execute.c b/execute.c index b102a4a..3ed645a 100644 --- a/execute.c +++ b/execute.c @@ -36,6 +36,9 @@ #include +#include +#include + #include "execute.h" /* Terminate a string representing a filename at the final '/' to @@ -112,8 +115,123 @@ exists (const char *path) return 1; } -/* Given "library" filename resolve it to an absolute path to an - * existing file as follows: +/* Given a program name, search the PATH environment variable and + * return the first absolute path to 'program'. + * + * Returns: A string talloc'ed to 'ctx'. + * + * Note: This function aborts the current program if 'program' cannot + * be located by searching PATH. + */ +static char * +search_path_for_program (void *ctx, const char *program) +{ + char *orig_path, *path, *colon, *dir, *candidate; + void *local = talloc_new (ctx); + + /* If the program name already contains a slash, then this is + * an absolute (or relative) path. Either way, we don't search + * PATH, since we can directly open this filename. */ + if (strchr (program, '/')) + return talloc_strdup (ctx, program); + + orig_path = path = getenv ("PATH"); + + while (*path) { + colon = strchr (path, ':'); + + if (colon) { + dir = talloc_strndup (local, path, colon - path); + path = colon + 1; + } else { + dir = path; + path = path + strlen (path); + } + + candidate = talloc_asprintf(local, "%s/%s", dir, program); + + if (exists (candidate)) { + talloc_steal (ctx, candidate); + talloc_free (local); + return candidate; + } else { + talloc_free (candidate); + } + } + + fprintf (stderr, "Cannot find program %s (looked in %s)\n", + program, orig_path); + exit (1); +} + +/* Is the given elf program 32 or 64 bit? + * + * Note: This function aborts the current program if 'program' cannot + * be opened as a valid ELF file. */ +static int +elf_bits (const char *program) +{ + Elf *elf; + GElf_Ehdr ehdr; + int fd, class; + void *local = talloc_new (NULL); + char *absolute_program = search_path_for_program (local, program); + + fd = open (absolute_program, O_RDONLY, 0); + if (fd < 0) { + fprintf (stderr, "Failed to open %s: %s\n", absolute_program, + strerror (errno)); + exit (1); + } + + if (elf_version (EV_CURRENT ) == EV_NONE) { + fprintf (stderr, "Failed to initialize elf library: %s\n", + elf_errmsg (-1)); + exit (1); + } + + elf = elf_begin (fd, ELF_C_READ, NULL); + if (elf == NULL) { + fprintf (stderr, "Call to elf_begin on %s failed: %s\n", + absolute_program, elf_errmsg(-1)); + exit (1); + } + + if (elf_kind (elf) != ELF_K_ELF) { + fprintf (stderr, "Not an ELF object: %s\n", absolute_program); + exit (1); + } + + if (gelf_getehdr (elf, &ehdr) == NULL) { + fprintf (stderr, "getehdr on %s failed: %s\n", + absolute_program, elf_errmsg (-1)); + exit (1); + } + + class = gelf_getclass (elf); + + if (class == ELFCLASSNONE) { + fprintf (stderr, "getclass on %s failed: %s\n", + absolute_program, elf_errmsg (-1)); + exit (1); + } + + talloc_free (local); + + if (class == ELFCLASS32) + return 32; + else + return 64; + +} + +/* Find the appropriate path to the libfips wrapper. + * + * This involves, first, examining the elf header of the 'program' + * binary to be executed to know whether we should look for + * libfips-32.so or libfips-64.so. + * + * Next, we find the absolute patch containing the library as follows: * * 1. Look in same directory as current executable image * @@ -134,9 +252,14 @@ exists (const char *path) * Returns: a string talloc'ed to 'ctx' */ static char * -resolve_path (void *ctx, const char *library) +find_libfips_path (void *ctx, const char *program) { - char *bin_path, *lib_path; + char *bin_path, *library, *lib_path; + int bits; + + bits = elf_bits (program); + + library = talloc_asprintf(ctx, "libfips-%d.so", bits); bin_path = get_bin_name (ctx); @@ -163,14 +286,11 @@ resolve_path (void *ctx, const char *library) exit (1); } -/* After forking, set LD_PRELOAD to preload "library" within child - * environment, then exec given arguments. - * - * The "library" argument is the filename (without path) of a shared - * library to load. The complete path will be resolved with - * resolve_library_path above. */ +/* After forking, set LD_PRELOAD to preload libfips-{32,64}.so within + * child environment, then exec given arguments. + */ static int -fork_exec_with_preload_and_wait (char * const argv[], const char *library) +fork_exec_with_fips_preload_and_wait (char * const argv[]) { pid_t pid; int i, status; @@ -182,7 +302,7 @@ fork_exec_with_preload_and_wait (char * const argv[], const char *library) void *ctx = talloc_new (NULL); char *lib_path; - lib_path = resolve_path (ctx, library); + lib_path = find_libfips_path (ctx, argv[0]); setenv ("LD_PRELOAD", lib_path, 1); @@ -210,7 +330,7 @@ fork_exec_with_preload_and_wait (char * const argv[], const char *library) } int -execute_with_preload (int argc, char * const argv[], const char *library) +execute_with_fips_preload (int argc, char * const argv[]) { char **execvp_args; int i; @@ -228,5 +348,5 @@ execute_with_preload (int argc, char * const argv[], const char *library) /* execvp needs final NULL */ execvp_args[i] = NULL; - return fork_exec_with_preload_and_wait (execvp_args, library); + return fork_exec_with_fips_preload_and_wait (execvp_args); }