X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=execute.c;h=cc01c436db2329e19184a7d651b3fe5e06efe5aa;hb=6014e77b9f7cf0570fe799fde240970a7cafb7ce;hp=8ce88e52cfa84ffada8525fedc9ee12bed8b2938;hpb=b32aa136d3e51a250e58c0fc28162b5e5fd52f67;p=fips diff --git a/execute.c b/execute.c index 8ce88e5..cc01c43 100644 --- a/execute.c +++ b/execute.c @@ -19,12 +19,8 @@ * THE SOFTWARE. */ -#include "config.h" +#include "fips.h" -#include -#include - -#include #include #include @@ -81,20 +77,20 @@ get_bin_name (void *ctx) * of the filename being linked to). Go figure. */ int name_len = PATH_MAX + 1; - name = talloc_size (ctx, name_len - 1); + name = talloc_size (ctx, name_len); if (name == NULL) { fprintf (stderr, "Out of memory.\n"); exit (1); } - name_len = readlink (link, name, name_len); + name_len = readlink (link, name, name_len - 1); if (name_len < 0) { fprintf (stderr, "Failed to readlink %s: %s\n", link, strerror (errno)); exit (1); } - name[name_len + 1] = '\0'; + name[name_len] = '\0'; return name; } @@ -115,6 +111,55 @@ exists (const char *path) return 1; } +/* 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 @@ -125,10 +170,12 @@ 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 (program, O_RDONLY, 0); + fd = open (absolute_program, O_RDONLY, 0); if (fd < 0) { - fprintf (stderr, "Failed to open %s: %s\n", program, + fprintf (stderr, "Failed to open %s: %s\n", absolute_program, strerror (errno)); exit (1); } @@ -142,29 +189,31 @@ elf_bits (const char *program) elf = elf_begin (fd, ELF_C_READ, NULL); if (elf == NULL) { fprintf (stderr, "Call to elf_begin on %s failed: %s\n", - program, elf_errmsg(-1)); + absolute_program, elf_errmsg(-1)); exit (1); } if (elf_kind (elf) != ELF_K_ELF) { - fprintf (stderr, "Not an ELF object: %s\n", program); + 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", - program, elf_errmsg (-1)); + absolute_program, elf_errmsg (-1)); exit (1); } class = gelf_getclass (elf); if (class == ELFCLASSNONE) { - fprintf (stderr, "getclass on %s failed: %s\n", program, - elf_errmsg (-1)); + fprintf (stderr, "getclass on %s failed: %s\n", + absolute_program, elf_errmsg (-1)); exit (1); } + talloc_free (local); + if (class == ELFCLASS32) return 32; else @@ -230,55 +279,18 @@ find_libfips_path (void *ctx, const char *program) "\t%s\n" "and\n" "\t%s/" BINDIR_TO_LIBFIPSDIR "\n", bin_path, bin_path); - exit (1); -} -/* After forking, set LD_PRELOAD to preload libfips-{32,64}.so within - * child environment, then exec given arguments. - */ -static int -fork_exec_with_fips_preload_and_wait (char * const argv[]) -{ - pid_t pid; - int i, status; - - pid = fork (); - - /* Child */ - if (pid == 0) { - void *ctx = talloc_new (NULL); - char *lib_path; - - lib_path = find_libfips_path (ctx, argv[0]); - - setenv ("LD_PRELOAD", lib_path, 1); - - talloc_free (ctx); - - execvp (argv[0], argv); - fprintf (stderr, "Failed to execute:"); - for (i = 0; argv[i]; i++) { - fprintf (stderr, " %s", argv[i]); - } - fprintf (stderr, "\n"); - exit (1); - } - - /* Parent */ - waitpid (pid, &status, 0); - if (WIFEXITED (status)) { - return (WEXITSTATUS (status)); - } - if (WIFSIGNALED (status)) { - fprintf (stderr, "Child terminated by signal %d\n", - WTERMSIG (status)); - } - return 1; + fprintf(stderr, "\nIt's possible fips was not compiled with support for %d-bit applications.\n", bits); + fprintf(stderr, "Perhaps you need to install gcc-multilib and re-compile fips?\n"); + exit (1); } int execute_with_fips_preload (int argc, char * const argv[]) { + void *ctx = talloc_new (NULL); + char *lib_path; + char *ld_preload_value; char **execvp_args; int i; @@ -295,5 +307,27 @@ execute_with_fips_preload (int argc, char * const argv[]) /* execvp needs final NULL */ execvp_args[i] = NULL; - return fork_exec_with_fips_preload_and_wait (execvp_args); + lib_path = find_libfips_path (ctx, argv[0]); + + ld_preload_value = getenv ("LD_PRELOAD"); + + if (ld_preload_value) { + ld_preload_value = talloc_asprintf(ctx, "%s:%s", + ld_preload_value, + lib_path); + } else { + ld_preload_value = lib_path; + } + + setenv ("LD_PRELOAD", ld_preload_value, 1); + + talloc_free (ctx); + + execvp (argv[0], argv); + fprintf (stderr, "Failed to execute:"); + for (i = 0; argv[i]; i++) { + fprintf (stderr, " %s", argv[i]); + } + fprintf (stderr, "\n"); + exit (1); }